Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
fr_public/werkkzeug3/genbitmap.cpp
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
3939 lines (3320 sloc)
87.4 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // This file is distributed under a BSD license. See LICENSE.txt for details. | |
| #include "genbitmap.hpp" | |
| #include "fried/fried.hpp" | |
| #include "mmintrin.h" | |
| #include "xmmintrin.h" | |
| #include "ivec.h" | |
| #if sLINK_ENGINE | |
| #include "_start.hpp" | |
| #include "genoverlay.hpp" | |
| #include "genminmesh.hpp" | |
| #include "rtmanager.hpp" | |
| #endif | |
| #define SCRIPTVERIFY(x) {if(!(x)) return 0;} | |
| #define SCRIPTVERIFYVOID(x) {return 0; } | |
| #if 0 | |
| #define NOTEXTURES0() return NewBitmap(4,4); | |
| #define NOTEXTURES1(a) if(a) a->Release(); return NewBitmap(4,4); | |
| #define NOTEXTURES2(a,b) if(a) a->Release(); if(b) b->Release(); return NewBitmap(4,4); | |
| #define NOTEXTURES3(a,b,c) if(a) a->Release(); if(b) b->Release(); if(c) c->Release(); return NewBitmap(4,4); | |
| #else | |
| #define NOTEXTURES0() | |
| #define NOTEXTURES1(a) | |
| #define NOTEXTURES2(a,b) | |
| #define NOTEXTURES3(a,b,c) | |
| #endif | |
| // rules: | |
| // - first all SCRIPTVERIFY | |
| // - then CheckBitmap() | |
| // - after CheckBitmap you may not return 0 | |
| // | |
| // if return 0, then caller calls Release() for every argument. | |
| // if return !=0, then routine calls Release() for every argument | |
| // (except what it may return) | |
| /****************************************************************************/ | |
| sInt GenBitmapTextureSizeOffset; // 0 = normal, -1 = smaller, 1 = large | |
| sInt GenBitmapDefaultFormat = sTF_A8R8G8B8; | |
| #define BI_ADD 0 | |
| #define BI_SUB 1 | |
| #define BI_MUL 2 | |
| #define BI_DIFF 3 | |
| #define BI_ALPHA 4 | |
| #define BI_MULCOL 5 | |
| #define BI_ADDCOL 6 | |
| #define BI_SUBCOL 7 | |
| #define BI_GRAY 8 | |
| #define BI_INVERT 9 | |
| #define BI_SCALECOL 10 | |
| #define BI_MERGE 11 | |
| #define BI_BRIGHTNESS 12 | |
| #define BI_SUBR 13 | |
| #define BI_MULMERGE 14 | |
| #define BI_SHARPEN 15 | |
| #define BI_HARDLIGHT 0x10 | |
| #define BI_OVER 0x11 | |
| #define BI_ADDSMOOTH 0x12 | |
| #define BI_MIN 0x13 | |
| #define BI_MAX 0x14 | |
| #define BI_RANGE 0x15 // alway last | |
| /****************************************************************************/ | |
| /*** ***/ | |
| /*** Helpers ***/ | |
| /*** ***/ | |
| /****************************************************************************/ | |
| static GenBitmap *NewBitmap(sInt xs,sInt ys) | |
| { | |
| GenBitmap *bm; | |
| sBool dontscale = xs & 0x80; | |
| xs &= 0x7f; | |
| if(!dontscale) | |
| { | |
| xs += GenBitmapTextureSizeOffset; | |
| ys += GenBitmapTextureSizeOffset; | |
| } | |
| xs = sRange(xs,12,0); | |
| ys = sRange(ys,12,0); | |
| bm = new GenBitmap; | |
| bm->Init(1<<xs,1<<ys); | |
| return bm; | |
| } | |
| static sBool CheckBitmap(GenBitmap *&bm,GenBitmap **inbm=0) | |
| { | |
| GenBitmap *oldbm = bm; | |
| if(inbm) | |
| *inbm = bm; | |
| if(bm==0) | |
| return 1; | |
| if(bm->ClassId!=KC_BITMAP) | |
| return 1; | |
| if(bm->Data==0) | |
| return 1; | |
| if(bm->RefCount>1) | |
| { | |
| if(inbm) | |
| { | |
| bm->Release(); | |
| bm = new GenBitmap; | |
| bm->Init(oldbm->XSize,oldbm->YSize); | |
| } | |
| else | |
| { | |
| oldbm = bm; | |
| bm = (GenBitmap *)oldbm->Copy(); | |
| oldbm->Release(); | |
| } | |
| } | |
| return 0; | |
| } | |
| sInt sRange7fff(sInt a) | |
| { | |
| if((unsigned) a < 0x7fff) | |
| return a; | |
| else if(a<0) | |
| return 0; | |
| else | |
| return 0x7fff; | |
| } | |
| sU64 GetColor64(const sInt *i) | |
| { | |
| sU64 col; | |
| col = ((sU64)sRange7fff(i[2]/2))<<0 | |
| | ((sU64)sRange7fff(i[1]/2))<<16 | |
| | ((sU64)sRange7fff(i[0]/2))<<32 | |
| | ((sU64)sRange7fff(i[3]/2))<<48; | |
| return col; | |
| } | |
| sU64 GetColor64(sU32 c) | |
| { | |
| sU64 col; | |
| col = c; | |
| col = ((col&0xff000000)<<24) | |
| | ((col&0x00ff0000)<<16) | |
| | ((col&0x0000ff00)<< 8) | |
| | ((col&0x000000ff) ); | |
| col = ((col | (col<<8))>>1)&0x7fff7fff7fff7fff; | |
| return col; | |
| } | |
| sU32 GetColor32(const sInt4 &colx) | |
| { | |
| sU32 col; | |
| col = (((sU32)sRange<sInt>(colx.z>>8,0xff,0))<<0 ) | |
| | (((sU32)sRange<sInt>(colx.y>>8,0xff,0))<<8 ) | |
| | (((sU32)sRange<sInt>(colx.x>>8,0xff,0))<<16) | |
| | (((sU32)sRange<sInt>(colx.w>>8,0xff,0))<<24); | |
| return col; | |
| } | |
| void Fade64(sU64 &r,sU64 &c0,sU64 &c1,sInt fade) | |
| { | |
| static const sU64 xor0 = 0xffffffff00000000; | |
| static const sU64 add0 = 0x0000800100000000; | |
| __asm | |
| { | |
| mov eax, [c0]; | |
| movq mm2, [eax]; | |
| mov eax, [c1]; | |
| movq mm3, [eax]; | |
| movd mm0, [fade]; | |
| punpckldq mm0, mm0; | |
| psrad mm0, 1; | |
| pxor mm0, [xor0]; | |
| paddd mm0, [add0]; | |
| packssdw mm0, mm0; | |
| punpcklwd mm0, mm0; | |
| movq mm1, mm0; | |
| punpcklwd mm0, mm0; | |
| punpckhwd mm1, mm1; | |
| mov eax, [r]; | |
| pmulhw mm3, mm0; | |
| pmulhw mm2, mm1; | |
| paddw mm2, mm3; | |
| psllw mm2, 1; | |
| movq [eax], mm2; | |
| emms; | |
| } | |
| } | |
| void AddScale64(sU64 &r,sU64 &c0,sU64 &c1,sInt fade) | |
| { | |
| __asm | |
| { | |
| mov eax, [c0]; | |
| movq mm2, [eax]; | |
| mov eax, [c1]; | |
| movq mm3, [eax]; | |
| movd mm0, [fade]; | |
| psrad mm0, 1; | |
| packssdw mm0, mm0; | |
| punpcklwd mm0, mm0; | |
| punpcklwd mm0, mm0; | |
| mov eax, [r]; | |
| pmulhw mm3, mm0; | |
| psllw mm3, 1; | |
| paddsw mm2, mm3; | |
| movq [eax], mm2; | |
| emms; | |
| } | |
| } | |
| void BilinearSetup(BilinearContext *ctx,sU64 *src,sInt w,sInt h,sInt b) | |
| { | |
| ctx->Src = src; | |
| ctx->XShift = sGetPower2(w)+3; | |
| ctx->XSize1 = (w-1)<<3; | |
| ctx->YSize1 = h-1; | |
| ctx->XMax1 = (w << 16) - 1; | |
| ctx->YMax1 = (h << 16) - 1; | |
| ctx->XAm = (b&1) ? 0xffffffff : ctx->XMax1; | |
| ctx->YAm = (b&2) ? 0xffffffff : ctx->YMax1; | |
| /*ctx->XAm = ((b&1) ? 0xffffffff : w-1) << 3; | |
| ctx->YAm = (b&2) ? 0xffffffff : h-1;*/ | |
| } | |
| void PointFilter(BilinearContext *ctx,sU64 *r,sInt u,sInt v) | |
| { | |
| sInt x = (u>>13)&(ctx->XSize1); | |
| sInt y = (v>>16)&(ctx->YSize1); | |
| const sU8 *ptr = (const sU8 *) ctx->Src; | |
| ptr += (y<<ctx->XShift) + x; | |
| *r = *(const sU64 *) ptr; | |
| } | |
| void BilinearFilter(BilinearContext *ctx,sU64 *r,sInt u,sInt v) | |
| { | |
| static const sU64 adjust = 0x8000800080008000; | |
| #if 1 | |
| __asm | |
| { | |
| mov esi, [ctx]; | |
| mov edi, [esi]BilinearContext.Src; | |
| // clamp u, v | |
| mov eax, [u]; | |
| mov ebx, [v]; | |
| and eax, [esi]BilinearContext.XAm; | |
| and ebx, [esi]BilinearContext.YAm; | |
| cmp eax, [esi]BilinearContext.XMax1; | |
| jbe okx; | |
| sar eax, 31; | |
| not eax; | |
| and eax, [esi]BilinearContext.XMax1; | |
| okx: | |
| cmp ebx, [esi]BilinearContext.YMax1; | |
| jbe oky; | |
| sar ebx, 31; | |
| not ebx; | |
| and ebx, [esi]BilinearContext.YMax1; | |
| oky: | |
| movd mm0, eax; | |
| movd mm1, ebx; | |
| // calc s0, s1, u0, u1 | |
| mov ecx, [esi]BilinearContext.XShift; | |
| shr eax, 13; // u0 (pix offset) | |
| shr ebx, 16; // v0 (line count) | |
| and eax, not 7; // eax=u0 | |
| lea edx, [ebx+1]; | |
| shl ebx, cl; | |
| and edx, [esi]BilinearContext.YSize1; | |
| add ebx, edi; // ebx=s0 | |
| shl edx, cl; | |
| lea ecx, [eax+8]; | |
| add edi, edx; // edi=s1 | |
| and ecx, [esi]BilinearContext.XSize1; // ecx=u1 | |
| // load pixels | |
| movq mm2, [ebx+eax]; | |
| movq mm3, [ebx+ecx]; | |
| movq mm4, [edi+eax]; | |
| movq mm5, [edi+ecx]; | |
| // actual sample | |
| movq mm6, [adjust]; | |
| punpcklwd mm0, mm0; | |
| punpcklwd mm1, mm1; | |
| mov eax, [r]; | |
| punpcklwd mm0, mm0; | |
| punpcklwd mm1, mm1; | |
| psrlw mm0, 1; | |
| psrlw mm1, 1; | |
| // horiz | |
| psubw mm3, mm2; | |
| psubw mm5, mm4; | |
| pmulhw mm3, mm0; | |
| pmulhw mm5, mm0; | |
| psllw mm3, 1; | |
| psllw mm5, 1; | |
| paddw mm2, mm3; | |
| paddw mm4, mm5; | |
| // vert+write | |
| psubw mm4, mm2; | |
| paddw mm2, mm6; | |
| pmulhw mm4, mm1; | |
| psllw mm4, 1; | |
| paddw mm2, mm4; | |
| psubusw mm2, mm6; | |
| movntq [eax], mm2; | |
| emms; | |
| } | |
| #else | |
| __asm | |
| { | |
| mov esi, [ctx]; | |
| mov edi, [esi]BilinearContext.Src; | |
| movd mm1, [v]; | |
| // calc s0 | |
| mov eax, [v]; | |
| lea ebx, [eax-0x80000000]; | |
| sar eax, 16; | |
| sar ebx, 31; | |
| mov edx, eax; | |
| mov ecx, [esi]BilinearContext.XShift; | |
| and eax, [esi]BilinearContext.YAm; | |
| and ebx, [esi]BilinearContext.YSize1; | |
| cmp eax, [esi]BilinearContext.YSize1; | |
| jbe ok1; | |
| mov eax, ebx; | |
| ok1: | |
| shl eax, cl; | |
| add edi, eax; | |
| movd mm0, [u]; | |
| // calc s1 | |
| lea eax, [edx+1]; | |
| lea ebx, [edx+0x7fffffff]; | |
| and eax, [esi]BilinearContext.YAm; | |
| sar ebx, 31; | |
| and ebx, [esi]BilinearContext.YSize1; | |
| cmp eax, [esi]BilinearContext.YSize1; | |
| jbe ok2; | |
| mov eax, ebx; | |
| ok2: | |
| shl eax, cl; | |
| add eax, [esi]BilinearContext.Src; | |
| mov ecx, eax; | |
| // u+0 | |
| mov eax, [u]; | |
| lea ebx, [eax-0x80000000]; | |
| sar eax, 13; | |
| sar ebx, 31; | |
| mov edx, eax; | |
| and eax, [esi]BilinearContext.XAm; | |
| and ebx, [esi]BilinearContext.XSize1; | |
| cmp eax, [esi]BilinearContext.XSize1; | |
| jbe ok3; | |
| mov eax, ebx; | |
| ok3: | |
| movq mm2, [edi+eax]; | |
| movq mm4, [ecx+eax]; | |
| // u+1 | |
| lea eax, [edx+8]; | |
| lea ebx, [edx+0x7ffffff8]; | |
| and eax, [esi]BilinearContext.XAm; | |
| sar ebx, 31; | |
| and ebx, [esi]BilinearContext.XSize1; | |
| cmp eax, [esi]BilinearContext.XSize1; | |
| jbe ok4; | |
| mov eax, ebx; | |
| ok4: | |
| movq mm3, [edi+eax]; | |
| movq mm5, [ecx+eax]; | |
| // actual sample | |
| movq mm6, [adjust]; | |
| punpcklwd mm0, mm0; | |
| punpcklwd mm1, mm1; | |
| mov eax, [r]; | |
| punpcklwd mm0, mm0; | |
| punpcklwd mm1, mm1; | |
| psrlw mm0, 1; | |
| psrlw mm1, 1; | |
| // horiz | |
| psubw mm3, mm2; | |
| psubw mm5, mm4; | |
| pmulhw mm3, mm0; | |
| pmulhw mm5, mm0; | |
| psllw mm3, 1; | |
| psllw mm5, 1; | |
| paddw mm2, mm3; | |
| paddw mm4, mm5; | |
| // vert+write | |
| psubw mm4, mm2; | |
| paddw mm2, mm6; | |
| pmulhw mm4, mm1; | |
| psllw mm4, 1; | |
| paddw mm2, mm4; | |
| psubusw mm2, mm6; | |
| movntq [eax], mm2; | |
| emms; | |
| } | |
| #endif | |
| } | |
| static sInt GammaTable[1025]; | |
| static sInt GetGamma(sInt value) | |
| { | |
| sInt vi = value >> 5; | |
| return GammaTable[vi] + (((GammaTable[vi+1]-GammaTable[vi]) * (value & 31)) >> 5); | |
| } | |
| /****************************************************************************/ | |
| /*** ***/ | |
| /*** Operators ***/ | |
| /*** ***/ | |
| /****************************************************************************/ | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Flat(sInt xs,sInt ys,sU32 color) | |
| { | |
| NOTEXTURES0(); | |
| GenBitmap *bm; | |
| bm = NewBitmap(xs,ys); | |
| sSetMem8(bm->Data,GetColor64(color),bm->Size); | |
| return bm; | |
| } | |
| GenBitmap * __stdcall Bitmap_Format(GenBitmap *bm,sInt format,sInt count,sInt tresh) | |
| { | |
| NOTEXTURES1(bm); | |
| SCRIPTVERIFY(format>0); | |
| if(CheckBitmap(bm)) return 0; | |
| bm->Format = format; | |
| bm->TexMipCount = count; | |
| bm->TexMipTresh = tresh; | |
| return bm; | |
| } | |
| #if sLINK_ENGINE | |
| GenBitmap * __stdcall Bitmap_RenderTarget(sInt xs,sInt ys,sU32 format) | |
| { | |
| GenBitmap *bm; | |
| bm = new GenBitmap; | |
| bm->Format = format; | |
| bm->XSize = 1<<xs; | |
| bm->YSize = 1<<ys; | |
| bm->Texture = sSystem->AddTexture(1<<xs,1<<ys,format,0); | |
| return bm; | |
| } | |
| #endif | |
| /****************************************************************************/ | |
| void __stdcall Bitmap_Inner(sU64 *d,sU64 *s,sInt count,sInt mode,sU64 *x=0) | |
| { | |
| static const sU64 mask1 = 0x8000800080008000; | |
| __asm | |
| { | |
| emms | |
| mov esi,[s] | |
| mov edi,[d] | |
| mov ebx,[x] | |
| mov ecx,[count] | |
| mov edx,[mode] | |
| pcmpeqb mm3,mm3; | |
| psrlw mm3,1; ; mm3 = 0x7fff7fff7fff7fff | |
| pcmpeqb mm4,mm4 | |
| psrlq mm4,16 ; mm4 = 0x00007fff7fff7fff | |
| pcmpeqb mm5,mm5 | |
| pxor mm5,mm4 ; mm5 = 0x7fff000000000000 | |
| psrlw mm4,1 | |
| psrlw mm5,1 | |
| movq mm2,[esi] ; mm2 = data[0] | |
| pcmpeqb mm7,mm7; | |
| psrlw mm7,2; ; mm7 = 0x3fff3fff3fff3fff | |
| pxor mm6,mm6 ; mm6 = 0x0000000000000000 | |
| shl ecx,3; ; ecx = number of bytes | |
| add esi,ecx; ; esi = end of source | |
| add edi,ecx; ; edi = end of dest | |
| add ebx,ecx; ; ebx = end of source2 | |
| neg ecx | |
| lea eax,loop0 | |
| dec edx | |
| js loop_start | |
| lea eax,loop1 | |
| dec edx | |
| js loop_start | |
| lea eax,loop2 | |
| dec edx | |
| js loop_start | |
| lea eax,loop3 | |
| dec edx | |
| js loop_start | |
| lea eax,loop4 | |
| dec edx | |
| js loop_start | |
| lea eax,loop5 | |
| dec edx | |
| js loop_start | |
| lea eax,loop6 | |
| dec edx | |
| js loop_start | |
| lea eax,loop7 | |
| dec edx | |
| js loop_start | |
| lea eax,loop8 | |
| dec edx | |
| js loop_start | |
| lea eax,loop9 | |
| dec edx | |
| js loop_start | |
| lea eax,loopa | |
| dec edx | |
| js loop_start | |
| lea eax,loopb | |
| dec edx | |
| js loop_start | |
| lea eax,loopc | |
| dec edx | |
| js loop_start | |
| lea eax,loopd | |
| dec edx | |
| js loop_start | |
| lea eax,loop0e | |
| dec edx | |
| js loop_start | |
| lea eax,loop0f | |
| dec edx | |
| js loop_start | |
| lea eax,loop10 | |
| dec edx | |
| js loop_start | |
| lea eax,loop11 | |
| dec edx | |
| js loop_start | |
| lea eax,loop12 | |
| dec edx | |
| js loop_start | |
| lea eax,loop13 | |
| dec edx | |
| js loop_start | |
| lea eax,loop14 | |
| dec edx | |
| js loop_start | |
| movq mm7,[esi+ecx+8] ; mm7 = data[1] | |
| psubsw mm7,mm2 | |
| pxor mm1,mm1 | |
| lea eax,loop15 | |
| loop_start: | |
| jmp eax | |
| loop0: // add | |
| movq mm0,[ebx+ecx]; | |
| paddsw mm0,[esi+ecx]; | |
| jmp loopo; | |
| loop1: // sub | |
| movq mm0,[ebx+ecx]; | |
| psubusw mm0,[esi+ecx]; | |
| jmp loopo | |
| loop2: // mul | |
| movq mm0,[ebx+ecx]; | |
| pmulhw mm0,[esi+ecx]; | |
| psllw mm0,1; | |
| jmp loopo | |
| loop3: // diff | |
| movq mm0,[ebx+ecx]; | |
| psubw mm0,[esi+ecx]; | |
| paddw mm0,mm3 | |
| psrlw mm0,1 | |
| jmp loopo | |
| loop4: // alpha | |
| movq mm0,[esi+ecx] | |
| movq mm1,[ebx+ecx] | |
| movq mm6,mm0 | |
| movq mm7,mm0 | |
| psrlq mm6,16 | |
| psrlq mm7,32 | |
| paddw mm0,mm6 | |
| paddw mm7,mm6 | |
| psrlw mm0,1 | |
| psrlw mm7,1 | |
| paddw mm0,mm7 | |
| pand mm1,mm4 | |
| psllq mm0,47 | |
| pand mm0,mm5 | |
| por mm0,mm1 | |
| jmp loopo | |
| loop5: // mul color | |
| movq mm0,[ebx+ecx] | |
| pmulhw mm0,mm2 | |
| psllw mm0,1 | |
| jmp loopo | |
| loop6: // add color | |
| movq mm0,[ebx+ecx] | |
| paddsw mm0,mm2 | |
| jmp loopo | |
| loop7: // sub color | |
| movq mm0,[ebx+ecx] | |
| psubusw mm0,mm2 | |
| jmp loopo | |
| loop8: // gray color | |
| movq mm0,[ebx+ecx] | |
| movq mm6, mm0; | |
| movq mm7, mm0; | |
| psrlq mm6, 16; | |
| psrlq mm7, 32; | |
| paddw mm0, mm6; | |
| paddw mm7, mm6; | |
| psrlw mm0, 1; | |
| psrlw mm7, 1; | |
| paddw mm0, mm7; | |
| psrlw mm0, 1; | |
| punpcklwd mm0, mm0; | |
| punpcklwd mm0, mm0; | |
| por mm0, mm5; | |
| jmp loopo | |
| loop9: // invert color | |
| movq mm0,[ebx+ecx] | |
| pxor mm0,mm3 | |
| jmp loopo | |
| loopa: // scale color | |
| movq mm0, [ebx+ecx]; | |
| movq mm1, mm0; | |
| pmullw mm0, mm2; | |
| pmulhw mm1, mm2; | |
| movq mm6, mm0; | |
| punpcklwd mm0, mm1; | |
| punpckhwd mm6, mm1; | |
| psrld mm0, 11; | |
| psrld mm6, 11; | |
| packssdw mm0, mm6; | |
| jmp loopo | |
| loopb: // merge | |
| movq mm0,[edi+ecx]; | |
| movq mm4,[esi+ecx]; | |
| movq mm5,[ebx+ecx]; | |
| movq mm1,mm3; | |
| psubsw mm1,mm0; | |
| pmulhw mm0,mm4; | |
| pmulhw mm1,mm5; | |
| paddsw mm0,mm1; | |
| psllw mm0,1 | |
| jmp loopo | |
| loopc: // brigtness | |
| movq mm0,[esi+ecx]; | |
| movq mm1,[ebx+ecx]; | |
| movq mm2,mm0 | |
| pcmpgtw mm2,mm7 | |
| psrlw mm2,1 | |
| pxor mm0,mm2 | |
| pxor mm1,mm2 | |
| pmulhw mm0,mm1 | |
| psllw mm0,2 | |
| pxor mm0,mm2 | |
| jmp loopo | |
| loopd: // subr | |
| movq mm0,[esi+ecx]; | |
| psubusw mm0,[ebx+ecx]; | |
| jmp loopo | |
| loop0e: // mulmerge | |
| movq mm0,[edi+ecx]; | |
| movq mm4,[esi+ecx]; | |
| movq mm5,[ebx+ecx]; | |
| movq mm1,mm3 | |
| pmulhw mm4,mm5 | |
| psllw mm4,1 | |
| psubsw mm1,mm0 | |
| pmulhw mm0,mm4 | |
| pmulhw mm1,mm5 | |
| paddsw mm0,mm1 | |
| psllw mm0,1 | |
| jmp loopo | |
| loop0f: // sharpen | |
| movq mm0,[ebx+ecx] | |
| movq mm3,mm0 | |
| psubusw mm0,[edi+ecx] | |
| movq mm1,mm0 | |
| pmullw mm0,mm2 | |
| pmulhw mm1,mm2 | |
| movq mm7,mm0 | |
| punpcklwd mm0,mm1 | |
| punpckhwd mm7,mm1 | |
| psrad mm0,11 | |
| psrad mm7,11 | |
| packssdw mm0,mm7 | |
| paddsw mm0,mm3 | |
| pmaxsw mm0,mm6 | |
| jmp loopo | |
| loop10: // hardlight | |
| movq mm1,[esi+ecx]; | |
| movq mm0,[ebx+ecx]; | |
| psllw mm1,1; | |
| movq mm2,mm1; | |
| pand mm1,mm3; | |
| psraw mm2,15; | |
| movq mm4,mm0; | |
| pmulhw mm0,mm1; | |
| psllw mm0,1; | |
| paddw mm1,mm4; | |
| pxor mm0,mm2; | |
| pand mm1,mm2; | |
| paddw mm0,mm1; | |
| jmp loopo | |
| loop11: // over | |
| movq mm0,[ebx+ecx]; | |
| movq mm1,[esi+ecx]; | |
| movq mm2,mm1; | |
| psubsw mm1,mm0; | |
| punpckhwd mm2,mm2; | |
| punpckhwd mm2,mm2; | |
| pmulhw mm1,mm2; | |
| psllw mm1,1; | |
| paddsw mm0,mm1; | |
| pmaxsw mm0,mm6; | |
| /*paddw mm0,[mask1]; | |
| psubsw mm0,[mask1];*/ | |
| jmp loopo | |
| loop12: // addsmooth (screen) | |
| movq mm0,[ebx+ecx]; | |
| movq mm1,[esi+ecx]; | |
| pxor mm0,mm3; | |
| pxor mm1,mm3; | |
| pmulhw mm0,mm1; | |
| psllw mm0,1; | |
| pxor mm0,mm3; | |
| jmp loopo; | |
| loop13: // min | |
| movq mm0,[ebx+ecx]; | |
| pminsw mm0,[esi+ecx]; | |
| jmp loopo; | |
| loop14: // max | |
| movq mm0,[ebx+ecx]; | |
| pmaxsw mm0,[esi+ecx]; | |
| jmp loopo; | |
| loop15: // color range | |
| movq mm0,[ebx+ecx] | |
| pmulhw mm0,mm7 | |
| psllw mm0,1 | |
| paddsw mm0,mm2 | |
| pmaxsw mm0,mm1 | |
| /*paddw mm0,mm6 | |
| psubusw mm0,mm6*/ | |
| loopo: | |
| movq [edi+ecx],mm0; | |
| add ecx, 8; | |
| je ende | |
| jmp eax | |
| ende: | |
| emms | |
| } | |
| } | |
| GenBitmap * __stdcall Bitmap_Merge(sInt mode,sInt count,GenBitmap *b0,...) | |
| { | |
| sInt i; | |
| GenBitmap *bi,*in; | |
| SCRIPTVERIFY(b0); | |
| SCRIPTVERIFY(b0->ClassId==KC_BITMAP); | |
| SCRIPTVERIFY(mode>=0 && mode<11); | |
| static sU8 modes[] = | |
| { | |
| BI_ADD,BI_SUB,BI_MUL,BI_DIFF,BI_ALPHA, | |
| BI_BRIGHTNESS, | |
| BI_HARDLIGHT,BI_OVER,BI_ADDSMOOTH, | |
| BI_MIN,BI_MAX | |
| }; | |
| mode = modes[mode]; | |
| // if(mode==5) mode=BI_BRIGHTNESS; // ***SIZE | |
| // if(mode>=6 && mode <=8) mode += BI_HARDLIGHT-6; | |
| for(i=1;i<count && (&b0)[i];i++) | |
| { | |
| bi = ((&b0)[i]); | |
| SCRIPTVERIFY(bi->ClassId==KC_BITMAP); | |
| if(b0->XSize!=bi->XSize || b0->YSize!=bi->YSize) | |
| return 0; | |
| } | |
| if(count == 1) | |
| return CheckBitmap(b0) ? 0 : b0; | |
| if(CheckBitmap(b0,&in)) return 0; | |
| i = 1; | |
| while(i<count && (&b0)[i]) | |
| { | |
| bi = ((&b0)[i]); | |
| sVERIFY(b0->XSize==bi->XSize && b0->YSize==bi->YSize); | |
| Bitmap_Inner(b0->Data,bi->Data,b0->Size,mode,in->Data); | |
| bi->Release(); | |
| in = b0; | |
| i++; | |
| } | |
| return b0; | |
| } | |
| GenBitmap * __stdcall Bitmap_Color(GenBitmap *bm,sInt mode,sU32 col) | |
| { | |
| NOTEXTURES1(bm); | |
| sU64 color; | |
| GenBitmap *in; | |
| SCRIPTVERIFY(mode>=0 && mode<6); | |
| if(CheckBitmap(bm,&in)) return 0; | |
| color = GetColor64(col); | |
| Bitmap_Inner(bm->Data,&color,bm->Size,mode+BI_MULCOL,in->Data); | |
| return bm; | |
| } | |
| GenBitmap * __stdcall Bitmap_Range(GenBitmap *bm,sInt mode,sU32 col0,sU32 col1) | |
| { | |
| NOTEXTURES1(bm); | |
| sU64 cx[2]; | |
| GenBitmap *in; | |
| SCRIPTVERIFY(mode>=0 && mode<6); | |
| if(CheckBitmap(bm,&in)) return 0; | |
| cx[0] = GetColor64(col0); | |
| cx[1] = GetColor64(col1); | |
| if(mode&1) | |
| { | |
| Bitmap_Inner(bm->Data,cx,bm->Size,BI_GRAY,in->Data); | |
| in = bm; | |
| } | |
| if(mode&2) | |
| { | |
| Bitmap_Inner(bm->Data,cx,bm->Size,BI_INVERT,in->Data); | |
| in = bm; | |
| } | |
| Bitmap_Inner(bm->Data,cx,bm->Size,BI_RANGE,in->Data); | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_GlowRect(GenBitmap *bm,sF32 cx,sF32 cy,sF32 rx,sF32 ry,sF32 sx,sF32 sy,sU32 color,sF32 alpha,sF32 power,sU32 wrap,sU32 bug) | |
| { | |
| NOTEXTURES1(bm); | |
| sU64 *d; | |
| sInt x,y; | |
| sF32 a; | |
| sInt f,fm; | |
| sU64 col; | |
| sF32 fx,fy,tresh; | |
| sInt LowTable[32]; | |
| sBool circular = (bug & 2) == 0; | |
| if(wrap==1) | |
| { | |
| if(cx+rx+sx> 1.0f) bm = Bitmap_GlowRect(bm,cx-1.0f,cy,rx,ry,sx,sy,color,alpha,power,2,bug); | |
| if(cx-rx-sx<-0.0f) bm = Bitmap_GlowRect(bm,cx+1.0f,cy,rx,ry,sx,sy,color,alpha,power,2,bug); | |
| } | |
| if(wrap==1 || wrap==2) | |
| { | |
| if(cy+ry+sy> 1.0f) bm = Bitmap_GlowRect(bm,cx,cy-1.0f,rx,ry,sx,sy,color,alpha,power,0,bug); | |
| if(cy-ry-sy<-0.0f) bm = Bitmap_GlowRect(bm,cx,cy+1.0f,rx,ry,sx,sy,color,alpha,power,0,bug); | |
| } | |
| if(CheckBitmap(bm)) return 0; | |
| if(power==0) power=(1.0f/65536.0f); | |
| power = 0.25/power; | |
| cx*=bm->XSize; | |
| cy*=bm->YSize; | |
| rx*=bm->XSize; | |
| ry*=bm->YSize; | |
| sx*=bm->XSize; | |
| sy*=bm->YSize; | |
| sInt icx=cx,icy=cy,isx=sx,isy=sy; | |
| tresh = 1.0f/65536.0f; | |
| if(rx<tresh) rx=tresh; | |
| rx = circular ? 1.0f/(rx*rx) : 1.0f / rx; | |
| if(ry<tresh) ry=tresh; | |
| ry = circular ? 1.0f/(ry*ry) : 1.0f / ry; | |
| alpha *= 32768.0f; | |
| col = GetColor64(color); | |
| fm = alpha; | |
| for(x=0;x<1025;x++) | |
| { | |
| if(bug & 1) | |
| GammaTable[x] = sRange7fff(sFPow(1.0f-x/1024.0f,power)*alpha)*2; | |
| else | |
| GammaTable[x] = sRange7fff((1.0f-sFPow(x/1024.0f,power*2.0f))*alpha)*2; | |
| } | |
| // there are very steep slopes around 0, so don't try approximating them | |
| for(x=0;x<32;x++) | |
| { | |
| if(bug & 1) | |
| LowTable[x] = sRange7fff(sFPow(1.0f-x/32768.0f,power)*alpha)*2; | |
| else | |
| LowTable[x] = sRange7fff((1.0f-sFPow(x/32768.0f,power*2.0f))*alpha)*2; | |
| } | |
| d = bm->Data; | |
| for(y=0;y<bm->YSize;y++) | |
| { | |
| fy = sFAbs(y-cy)-sy; | |
| if(fy<0) fy = 0; | |
| fy *= circular ? fy*ry : ry; | |
| for(x=0;x<bm->XSize;x++) | |
| { | |
| fx = sFAbs(x-cx)-sx; | |
| if(fx<0) fx = 0; | |
| a = circular ? fx*fx*rx+fy : sMax(fx*rx,fy); | |
| if(a<1.0f-1.0f/32768.0f) // to cull a few more pixels... | |
| { | |
| f = sFtol(a*32768); | |
| if(f<32) | |
| f = LowTable[f]; | |
| else | |
| f = GetGamma(f); | |
| Fade64(*d,*d,col,f); | |
| } | |
| d++; | |
| } | |
| while(x<bm->XSize); | |
| } | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Dots(GenBitmap *bm,sU32 color0,sU32 color1,sInt count,sInt seed) | |
| { | |
| NOTEXTURES1(bm); | |
| sU64 *d; | |
| sInt f; | |
| sInt x; | |
| sU64 c0,c1; | |
| if(CheckBitmap(bm)) return 0; | |
| c0 = GetColor64(color0); | |
| c1 = GetColor64(color1); | |
| count = sMulDiv(bm->Size,count,1<<12); | |
| sSetRndSeed(seed); | |
| d = bm->Data; | |
| do | |
| { | |
| f = sGetRnd(0x10000); | |
| x = sGetRnd(bm->Size); | |
| Fade64(d[x],c0,c1,f); | |
| count--; | |
| } | |
| while(count>0); | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| /*** ***/ | |
| /*** HSCB ***/ | |
| /*** ***/ | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_HSCB(GenBitmap *bm,sF32 fh,sF32 fs,sF32 fc,sF32 fb) | |
| { | |
| NOTEXTURES1(bm); | |
| GenBitmap *in; | |
| if(CheckBitmap(bm,&in)) return 0; | |
| sU16 *d,*s; | |
| sInt i; | |
| sInt ch,ffh,ffs; | |
| sInt cr,cg,cb,min,max,mm; | |
| sBool adjustHSV; | |
| d = (sU16 *) bm->Data; | |
| s = (sU16 *) in->Data; | |
| fc = fc*fc; | |
| for(i=0;i<1025;i++) | |
| GammaTable[i] = sFPow((i*32+0.01)/32768.0f,fc)*32768.0f*fb; | |
| ffh = sInt(fh * 6 * 65536) % (6*65536); | |
| ffs = fs * 65536; | |
| adjustHSV = ffh != 0 || ffs != 65536; | |
| for(i=0;i<bm->Size;i++) | |
| { | |
| // read, gamma, brightness | |
| // cr = sGamma[d[0]>>8]*fb; | |
| // cg = Gamma[d[1]>>8]*fb; | |
| // cb = Gamma[d[2]>>8]*fb; | |
| // if(fb<0) | |
| // { | |
| // cr = -65535*fb+cr; | |
| // cg = -65535*fb+cg; | |
| // cb = -65535*fb+cb; | |
| // } | |
| cr = GetGamma(s[2]); | |
| cg = GetGamma(s[1]); | |
| cb = GetGamma(s[0]); | |
| // convert to hsv | |
| if(adjustHSV) | |
| { | |
| max = sMax(cr,sMax(cg,cb)); | |
| min = sMin(cr,sMin(cg,cb)); | |
| mm = max - min; | |
| if(!mm) | |
| ch = 0; | |
| else | |
| { | |
| if(cr==max) | |
| ch = 1*65536 + sDivShift(cg-cb,mm); | |
| else if(cg==max) | |
| ch = 3*65536 + sDivShift(cb-cr,mm); | |
| else | |
| ch = 5*65536 + sDivShift(cr-cg,mm); | |
| } | |
| // adjust hue and saturation | |
| ch += ffh; | |
| mm = sMulShift(mm,ffs); | |
| min = max - mm; | |
| // convert to rgb | |
| if(ch>6*65536) ch-=6*65536; | |
| sInt rch = ch & 131071, m1, m2; | |
| m1 = min + ((rch >= 65536) ? sMulShift(rch - 65536,mm) : 0); | |
| m2 = min + ((rch < 65536) ? sMulShift(65536 - rch,mm) : 0); | |
| if(ch < 2*65536) | |
| { | |
| cr = max; | |
| cg = m1; | |
| cb = m2; | |
| } | |
| else if(ch < 4*65536) | |
| { | |
| cr = m2; | |
| cg = max; | |
| cb = m1; | |
| } | |
| else | |
| { | |
| cr = m1; | |
| cg = m2; | |
| cb = max; | |
| } | |
| } | |
| d[2] = sRange7fff(cr); | |
| d[1] = sRange7fff(cg); | |
| d[0] = sRange7fff(cb); | |
| d[3] = s[3]; | |
| d+=4; | |
| s+=4; | |
| } | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Wavelet(GenBitmap *bm,sInt mode,sInt count) | |
| { | |
| NOTEXTURES1(bm); | |
| sU64 *mem; | |
| sU16 *s,*d; | |
| sInt steps; | |
| sInt x,y,xs,ys,f,g; | |
| if(CheckBitmap(bm)) return 0; | |
| xs = bm->XSize; | |
| ys = bm->YSize; | |
| f = xs*4; | |
| g = xs*8; | |
| mem = new sU64[xs*ys]; | |
| for(steps = 0;steps<count;steps++) | |
| { | |
| d = (sU16 *) mem; | |
| s = (sU16 *) bm->Data; | |
| for(y=0;y<ys;y++) | |
| { | |
| for(x=0;x<xs/2;x++) | |
| { | |
| if(mode) | |
| { | |
| // c = b-a/2; | |
| // d = b+a/2; | |
| d[x*8+0] = sRange<sInt>(s[x*4+0+xs*2]-(s[x*4+0]-0x4000),0x7fff,0); | |
| d[x*8+1] = sRange<sInt>(s[x*4+1+xs*2]-(s[x*4+1]-0x4000),0x7fff,0); | |
| d[x*8+2] = sRange<sInt>(s[x*4+2+xs*2]-(s[x*4+2]-0x4000),0x7fff,0); | |
| d[x*8+3] = sRange<sInt>(s[x*4+3+xs*2]-(s[x*4+3]-0x4000),0x7fff,0); | |
| d[x*8+4] = sRange<sInt>(s[x*4+0+xs*2]+(s[x*4+0]-0x4000),0x7fff,0); | |
| d[x*8+5] = sRange<sInt>(s[x*4+1+xs*2]+(s[x*4+1]-0x4000),0x7fff,0); | |
| d[x*8+6] = sRange<sInt>(s[x*4+2+xs*2]+(s[x*4+2]-0x4000),0x7fff,0); | |
| d[x*8+7] = sRange<sInt>(s[x*4+3+xs*2]+(s[x*4+3]-0x4000),0x7fff,0); | |
| } | |
| else | |
| { | |
| // a = (d-c)/2 | |
| // b = (d+c)/2 | |
| d[x*4+0 ] = (s[x*8+4]-s[x*8+0]+0x8000L)/2; | |
| d[x*4+1 ] = (s[x*8+5]-s[x*8+1]+0x8000L)/2; | |
| d[x*4+2 ] = (s[x*8+6]-s[x*8+2]+0x8000L)/2; | |
| d[x*4+3 ] = (s[x*8+7]-s[x*8+3]+0x8000L)/2; | |
| d[x*4+0+xs*2] = (s[x*8+4]+s[x*8+0])/2; | |
| d[x*4+1+xs*2] = (s[x*8+5]+s[x*8+1])/2; | |
| d[x*4+2+xs*2] = (s[x*8+6]+s[x*8+2])/2; | |
| d[x*4+3+xs*2] = (s[x*8+7]+s[x*8+3])/2; | |
| } | |
| } | |
| s+=xs*4; | |
| d+=xs*4; | |
| } | |
| d = (sU16 *) bm->Data; | |
| s = (sU16 *) mem; | |
| for(x=0;x<xs;x++) | |
| { | |
| for(y=0;y<ys/2;y++) | |
| { | |
| if(mode) | |
| { | |
| d[y*g+0 ] = sRange<sInt>(s[y*f+0+ys*f/2]-(s[y*f+0]-0x4000),0x7fff,0); | |
| d[y*g+1 ] = sRange<sInt>(s[y*f+1+ys*f/2]-(s[y*f+1]-0x4000),0x7fff,0); | |
| d[y*g+2 ] = sRange<sInt>(s[y*f+2+ys*f/2]-(s[y*f+2]-0x4000),0x7fff,0); | |
| d[y*g+3 ] = sRange<sInt>(s[y*f+3+ys*f/2]-(s[y*f+3]-0x4000),0x7fff,0); | |
| d[y*g+0+f] = sRange<sInt>(s[y*f+0+ys*f/2]+(s[y*f+0]-0x4000),0x7fff,0); | |
| d[y*g+1+f] = sRange<sInt>(s[y*f+1+ys*f/2]+(s[y*f+1]-0x4000),0x7fff,0); | |
| d[y*g+2+f] = sRange<sInt>(s[y*f+2+ys*f/2]+(s[y*f+2]-0x4000),0x7fff,0); | |
| d[y*g+3+f] = sRange<sInt>(s[y*f+3+ys*f/2]+(s[y*f+3]-0x4000),0x7fff,0); | |
| } | |
| else | |
| { | |
| d[y*f+0 ] = (s[y*g+0+f]-s[y*g+0]+0x8000L)/2; | |
| d[y*f+1 ] = (s[y*g+1+f]-s[y*g+1]+0x8000L)/2; | |
| d[y*f+2 ] = (s[y*g+2+f]-s[y*g+2]+0x8000L)/2; | |
| d[y*f+3 ] = (s[y*g+3+f]-s[y*g+3]+0x8000L)/2; | |
| d[y*f+0+ys*f/2] = (s[y*g+0+f]+s[y*g+0])/2; | |
| d[y*f+1+ys*f/2] = (s[y*g+1+f]+s[y*g+1])/2; | |
| d[y*f+2+ys*f/2] = (s[y*g+2+f]+s[y*g+2])/2; | |
| d[y*f+3+ys*f/2] = (s[y*g+3+f]+s[y*g+3])/2; | |
| } | |
| } | |
| s+=4; | |
| d+=4; | |
| } | |
| } | |
| s = (sU16*)bm->Data; | |
| for(steps=0;steps<xs*ys+4;steps++) | |
| { | |
| *s = (*s)&0x7fe0; | |
| s++; | |
| } | |
| delete[] mem; | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| /*** ***/ | |
| /*** Blur ***/ | |
| /*** ***/ | |
| /****************************************************************************/ | |
| static void BlurCore(sU16 *p,sU16 *q,sInt sizek,sInt xRes,sInt f0,sInt f1,sInt amp,sInt ampc) | |
| { | |
| __m64 f0f1,amplo,amphi,ampclip; | |
| sInt mask; | |
| __asm | |
| { | |
| movd mm0, [f0]; | |
| punpcklwd mm0, [f1]; | |
| punpckldq mm0, mm0; | |
| movq [f0f1], mm0; | |
| movd mm0, [ampc]; | |
| movd mm1, [amp]; | |
| punpcklwd mm1, mm1; | |
| punpckldq mm0, mm0; | |
| movq mm2, mm1; | |
| movq [ampclip], mm0; | |
| punpcklwd mm1, mm1; | |
| punpckhwd mm2, mm2; | |
| movq [amplo], mm1; | |
| movq [amphi], mm2; | |
| mov eax, [f1]; | |
| sub eax, [f0]; | |
| movzx eax, ax; | |
| movd mm2, eax; | |
| punpckldq mm2, mm2; | |
| mov esi, [p]; | |
| mov edi, [q]; | |
| mov edx, [xRes]; | |
| dec edx; | |
| shl edx, 3; | |
| mov [mask], edx; | |
| mov eax, [sizek]; | |
| inc eax; | |
| sar eax, 1; | |
| neg eax; | |
| shl eax, 3; | |
| and eax, edx; | |
| mov edx, eax; | |
| // mm0 = akku0 | |
| // mm1 = akku1 | |
| // eax = s1 & mask | |
| // edx = s2 & mask | |
| // ecx = counter | |
| // esi = p | |
| // edi = q+d | |
| // seed first pixel | |
| movq mm0, [esi+edx] | |
| movq mm1, mm0 | |
| punpcklwd mm0, mm0 | |
| punpckhwd mm1, mm1 | |
| pmaddwd mm0, mm2 | |
| pmaddwd mm1, mm2 | |
| // init loop | |
| mov ecx, [sizek] | |
| test ecx, ecx | |
| jz xstartmain | |
| movq mm5, [f0f1] | |
| xinitloop: | |
| movq mm2, [esi+eax] | |
| add eax, 8 | |
| and eax, [mask]; | |
| movq mm3, [esi+eax] | |
| movq mm4, mm2 | |
| punpcklwd mm2, mm3 | |
| punpckhwd mm4, mm3 | |
| pmaddwd mm2, mm5 | |
| pmaddwd mm4, mm5 | |
| paddd mm0, mm2 | |
| paddd mm1, mm4 | |
| sub ecx, 1 | |
| jnz xinitloop | |
| xstartmain: | |
| mov ecx, [xRes] | |
| xmainloop: | |
| movq mm2, [esi+eax] | |
| movq mm5, [f0f1] | |
| add eax, 8 | |
| and eax, [mask] | |
| movq mm3, [esi+eax] | |
| movq mm4, mm2 | |
| punpcklwd mm2, mm3 // mix1 | |
| punpckhwd mm4, mm3 // mix2 | |
| pmaddwd mm2, mm5 | |
| pmaddwd mm4, mm5 | |
| paddd mm0, mm2 | |
| paddd mm1, mm4 | |
| movq mm2, mm0 | |
| movq mm3, mm1 | |
| movq mm5, [ampclip] | |
| psrad mm2, 6 | |
| psrad mm3, 6 | |
| movq mm6, mm0 | |
| movq mm7, mm1 | |
| movq mm4, mm2 | |
| punpcklwd mm2, mm3 | |
| punpckhwd mm4, mm3 | |
| pcmpgtd mm6, mm5 | |
| pcmpgtd mm7, mm5 | |
| movq mm5, [amplo] | |
| movq mm3, mm2 | |
| punpcklwd mm2, mm4 // mm2=aklo | |
| punpckhwd mm3, mm4 // mm3=akhi | |
| movq mm4, [amphi] | |
| packssdw mm6, mm7 // mm6=out | |
| pcmpeqb mm7, mm7 | |
| pmullw mm3, mm5 // mm3=akhi*amplo | |
| pmullw mm4, mm2 // mm4=aklo*amphi | |
| pmulhuw mm2, mm5 // mm2=aklo*amplo | |
| psllw mm7, 15 | |
| paddusw mm6, mm3 // out+=akhi*amplo | |
| movq mm3, [esi+edx] // pix1 | |
| add edx, 8 | |
| paddusw mm6, mm4 // out+=aklo*amphi | |
| and edx, [mask] | |
| movq mm5, [f0f1] | |
| paddusw mm6, mm2 // out+=aklo*amplo | |
| movq mm2, [esi+edx] // pix2 | |
| paddw mm6, mm7 // out+=add | |
| movq mm4, mm2 | |
| psubsw mm6, mm7 // out-=add | |
| punpcklwd mm2, mm3 // mix1 | |
| punpckhwd mm4, mm3 // mix2 | |
| pmaddwd mm2, mm5 | |
| pmaddwd mm4, mm5 | |
| movq [edi], mm6 // *(q+d) = out | |
| add edi, 8 | |
| psubd mm0, mm2 | |
| psubd mm1, mm4 | |
| sub ecx, 1 | |
| jnz xmainloop | |
| emms | |
| } | |
| } | |
| // registers are tight here, we don't want a frame pointer | |
| #pragma optimize("y",on) | |
| GenBitmap * __stdcall Bitmap_Blur(GenBitmap *bm,sInt flags,sF32 sx,sF32 sy,sF32 _amp) | |
| { | |
| NOTEXTURES1(bm); | |
| if(CheckBitmap(bm)) return 0; | |
| sInt x,y; | |
| sInt size,size2; | |
| sU32 mask; | |
| sInt s1,s2; | |
| sU16 *p,*q,*pp,*qq,*po,*qo; | |
| sInt ordercount; | |
| sInt amp,ampc,famp; | |
| sInt f0,f1; | |
| sInt order; | |
| // prepare | |
| order = flags & 15; | |
| if(order==0) return bm; | |
| pp = (sU16 *)bm->Data; | |
| qq = (sU16 *) new sU64[bm->Size]; | |
| // blur x | |
| size = sFtol(128*sx*bm->XSize); | |
| size2 = sFtol(128*sy*bm->YSize); | |
| famp = _amp * 65536.0f * 64; | |
| sInt repeat = 1; | |
| do | |
| { | |
| f1 = (size&127)/2; | |
| f0 = 64-f1; | |
| size = (size/128)*2; | |
| if(flags&0x10) | |
| size++; | |
| amp = famp / sMax<sInt>(1,size*64+f1*2); | |
| if(amp > 128) | |
| ampc = sDivShift(65536*64,amp) - 1; | |
| else | |
| ampc = 0x7fffffff; | |
| mask = bm->XSize * 4 - 1; | |
| po = pp; | |
| qo = qq; | |
| y = 0; | |
| do | |
| { | |
| pp = po + y*bm->XSize*4; | |
| qq = qo + y*bm->XSize*4; | |
| ordercount = order; | |
| do | |
| { | |
| p = pp; | |
| q = qq; | |
| pp = q; | |
| qq = p; | |
| BlurCore(p,q,size,bm->XSize,f0,f1,amp,ampc); | |
| ordercount--; | |
| } | |
| while(ordercount); | |
| y++; | |
| } | |
| while(y<bm->YSize); | |
| pp = po; | |
| qq = qo; | |
| if(order&1) | |
| sSwap(pp,qq); | |
| p = pp; | |
| q = qq; | |
| pp = q; | |
| qq = p; | |
| s1 = bm->YSize * 4; | |
| s2 = bm->XSize * 4; | |
| for(x=0;x<bm->XSize;x+=8) | |
| { | |
| p = qq + x*4; | |
| for(y=0;y<bm->YSize;y++) | |
| { | |
| __m64 m0,m1,m2,m3,m4,m5,m6,m7; | |
| m0 = *((__m64 *)(p+ 0)); | |
| m1 = *((__m64 *)(p+ 4)); | |
| m2 = *((__m64 *)(p+ 8)); | |
| m3 = *((__m64 *)(p+12)); | |
| m4 = *((__m64 *)(p+16)); | |
| m5 = *((__m64 *)(p+20)); | |
| m6 = *((__m64 *)(p+24)); | |
| m7 = *((__m64 *)(p+28)); | |
| *((__m64 *)(q+0*s1)) = m0; | |
| *((__m64 *)(q+1*s1)) = m1; | |
| *((__m64 *)(q+2*s1)) = m2; | |
| *((__m64 *)(q+3*s1)) = m3; | |
| *((__m64 *)(q+4*s1)) = m4; | |
| *((__m64 *)(q+5*s1)) = m5; | |
| *((__m64 *)(q+6*s1)) = m6; | |
| *((__m64 *)(q+7*s1)) = m7; | |
| q += 4; | |
| p += s2; | |
| } | |
| q += 7*s1; | |
| } | |
| sSwap(bm->XSize,bm->YSize); | |
| size = size2; | |
| } | |
| while(repeat--); | |
| __asm { emms }; | |
| sVERIFY(qq!=(sU16 *)bm->Data); | |
| delete[] qq; | |
| return bm; | |
| } | |
| #pragma optimize("",on) | |
| /****************************************************************************/ | |
| /*** ***/ | |
| /*** Mask ***/ | |
| /*** ***/ | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Mask(GenBitmap *bm,GenBitmap *bb,GenBitmap *bc,sInt mode) | |
| { | |
| NOTEXTURES1(bm); | |
| sInt size; | |
| GenBitmap *in; | |
| SCRIPTVERIFY(bb); | |
| SCRIPTVERIFY(bc); | |
| SCRIPTVERIFY(bb->ClassId==KC_BITMAP); | |
| SCRIPTVERIFY(bc->ClassId==KC_BITMAP); | |
| SCRIPTVERIFY(bm->Size==bb->Size); | |
| SCRIPTVERIFY(bm->Size==bc->Size); | |
| if(CheckBitmap(bm,&in)) return 0; | |
| size = bm->Size; | |
| Bitmap_Inner(bm->Data,bm->Data,size,BI_GRAY,in->Data); | |
| switch(mode) | |
| { | |
| case 0: | |
| Bitmap_Inner(bm->Data,bb->Data,size,BI_MERGE,bc->Data); | |
| break; | |
| case 1: | |
| Bitmap_Inner(bm->Data,bb->Data,size,BI_MUL,bm->Data); | |
| Bitmap_Inner(bm->Data,bc->Data,size,BI_ADD,bm->Data); | |
| break; | |
| case 2: | |
| Bitmap_Inner(bm->Data,bb->Data,size,BI_MUL,bm->Data); | |
| Bitmap_Inner(bm->Data,bc->Data,size,BI_SUBR,bm->Data); | |
| break; | |
| case 3: | |
| Bitmap_Inner(bm->Data,bb->Data,size,BI_MULMERGE,bc->Data); | |
| break; | |
| } | |
| bb->Release(); | |
| bc->Release(); | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| /*** ***/ | |
| /*** ***/ | |
| /*** ***/ | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Rotate(GenBitmap *bm,sF32 angle,sF32 sx,sF32 sy,sF32 tx,sF32 ty,sInt border,sInt newWidth,sInt newHeight) | |
| { | |
| NOTEXTURES1(bm); | |
| GenBitmap *in; | |
| sInt x,y; | |
| sU16 *d; | |
| sU64 *mem; | |
| sInt xs,ys; | |
| sInt txs,tys; | |
| sInt m00,m01,m10,m11,m20,m21; | |
| sF32 rotangle; | |
| BilinearContext ctx; | |
| SCRIPTVERIFY(sx!=0 && sy!=0); | |
| if(CheckBitmap(bm,&in)) return 0; | |
| // prepare | |
| xs = bm->XSize; | |
| ys = bm->YSize; | |
| txs = newWidth ? 1 << (newWidth - 1 + GenBitmapTextureSizeOffset) : xs; | |
| tys = newHeight ? 1 << (newHeight - 1 + GenBitmapTextureSizeOffset) : ys; | |
| mem = new sU64[txs * tys]; | |
| d = (sU16 *)mem; | |
| // rotate | |
| rotangle = angle*sPI2F; | |
| m00 = sFtol( sFCos(rotangle)*0x10000*xs/(sx*txs)); | |
| m01 = sFtol( sFSin(rotangle)*0x10000*ys/(sx*txs)); | |
| m10 = sFtol(-sFSin(rotangle)*0x10000*xs/(sy*tys)); | |
| m11 = sFtol( sFCos(rotangle)*0x10000*ys/(sy*tys)); | |
| #if sTEXTUREONLY || 1 | |
| m20 = sFtol( tx*xs*0x10000 - (txs*m00+tys*m10)/2); | |
| m21 = sFtol( ty*ys*0x10000 - (txs*m01+tys*m11)/2); | |
| #else | |
| m20 = sFtol( tx*xs*0x10000 - ((txs-1)*m00+(tys-1)*m10)/2); | |
| m21 = sFtol( ty*ys*0x10000 - ((txs-1)*m01+(tys-1)*m11)/2); | |
| #endif | |
| BilinearSetup(&ctx,in->Data,xs,ys,border); | |
| for(y=0;y<tys;y++) | |
| { | |
| sInt u = y*m10+m20; | |
| sInt v = y*m11+m21; | |
| if(border & 4) | |
| { | |
| for(x=0;x<txs;x++) | |
| { | |
| PointFilter(&ctx,(sU64 *)d,u,v); | |
| u += m00; | |
| v += m01; | |
| d += 4; | |
| } | |
| } | |
| else | |
| { | |
| for(x=0;x<txs;x++) | |
| { | |
| BilinearFilter(&ctx,(sU64 *)d,u,v); | |
| u += m00; | |
| v += m01; | |
| d += 4; | |
| } | |
| } | |
| } | |
| delete[] bm->Data; | |
| bm->XSize = txs; | |
| bm->YSize = tys; | |
| bm->Size = txs*tys; | |
| bm->Data = mem; | |
| return bm; | |
| } | |
| static sInt CSTable[2][1025]; | |
| static sInt CSLookup(const sInt *table,sInt value) | |
| { | |
| sInt ind = (value >> 6); | |
| return table[ind] + (((table[ind+1] - table[ind]) * (value & 63)) >> 6); | |
| } | |
| GenBitmap * __stdcall Bitmap_Twirl(GenBitmap *bm,sF32 strength,sF32 gamma,sF32 rx,sF32 ry,sF32 cx,sF32 cy,sInt border) | |
| { | |
| NOTEXTURES1(bm); | |
| GenBitmap *in; | |
| sInt x,y; | |
| sU16 *s,*d; | |
| sU64 *mem; | |
| sInt xs,ys; | |
| sInt px,py,dx,dy,u,v; | |
| BilinearContext ctx; | |
| if(CheckBitmap(bm,&in)) return 0; | |
| // prepare | |
| if(rx!=0 && ry!=0) | |
| { | |
| mem = new sU64[in->Size]; | |
| d = (sU16 *)mem; | |
| s = (sU16 *)in->Data; | |
| xs = in->XSize; | |
| ys = in->YSize; | |
| rx*=0.5f; | |
| ry*=0.5f; | |
| strength*=sPI2F; | |
| BilinearSetup(&ctx,(sU64 *)s,xs,ys,border); | |
| // calc table | |
| for(x=0;x<=1024;x++) | |
| { | |
| sF32 dist = sFPow(x / 1024.0f,gamma)*strength; | |
| sF32 dsin,dcos; | |
| sFSinCos(dist,dsin,dcos); | |
| CSTable[0][x] = 65536.0f * dsin; | |
| CSTable[1][x] = 65536.0f * dcos; | |
| } | |
| sInt fcx = cx * 65536.0f; | |
| sInt fcy = cy * 65536.0f; | |
| sInt frx = rx * 65536.0f; | |
| sInt fry = ry * 65536.0f; | |
| sInt xstep = 0x10000 / xs; | |
| sInt ystep = 0x10000 / ys; | |
| // rotate | |
| py = 0; | |
| for(y=0;y<ys;y++) | |
| { | |
| dy = py - fcy; | |
| sInt distb = 0x10000 - sMulDiv(dy,dy,fry); | |
| px = 0; | |
| for(x=0;x<xs;x++) | |
| { | |
| dx = px - fcx; | |
| sInt dist = distb - sMulDiv(dx,dx,frx); | |
| if(dist>0) | |
| { | |
| sInt fsin = CSLookup(CSTable[0],dist); | |
| sInt fcos = CSLookup(CSTable[1],dist); | |
| u = fcx + sMulShift(dx,fcos) + sMulShift(dy,fsin); | |
| v = fcy - sMulShift(dx,fsin) + sMulShift(dy,fcos); | |
| } | |
| else | |
| { | |
| u = px; | |
| v = py; | |
| } | |
| //BilinearFilter((sU64*)d,(sU64*)s,xs,ys,sFtol(u*0x10000*xs),sFtol(v*0x10000*ys),border); | |
| //BilinearFilter(&ctx,(sU64 *)d,sFtol(u*0x10000*xs),sFtol(v*0x10000*ys)); | |
| BilinearFilter(&ctx,(sU64 *)d,u*xs,v*ys); | |
| d+=4; | |
| px += xstep; | |
| } | |
| py += ystep; | |
| } | |
| delete[] bm->Data; | |
| bm->Data = mem; | |
| } | |
| else | |
| { | |
| bm->Copy(in); | |
| } | |
| return bm; | |
| } | |
| GenBitmap * __stdcall Bitmap_RotateMul(GenBitmap *bm,sF32 angle,sF32 sx,sF32 sy,sF32 tx,sF32 ty,sInt border,sU32 color,sInt mode,sInt count,sU32 fade) | |
| { | |
| NOTEXTURES1(bm); | |
| GenBitmap *bb,*bx; | |
| sInt cr,cg,cb,ca,i; | |
| SCRIPTVERIFY(count>0); | |
| SCRIPTVERIFY(bm); | |
| SCRIPTVERIFY(bm->ClassId==KC_BITMAP); | |
| bm = Bitmap_Color(bm,0,color); | |
| bb = (GenBitmap *)bm->Copy(); | |
| sF32 sgnx = sx < 0.0f ? -1.0f : 1.0f; | |
| sF32 sgny = sy < 0.0f ? -1.0f : 1.0f; | |
| sx *= sgnx; | |
| sy *= sgny; | |
| if(mode&16) | |
| { | |
| angle /= 1<<count; | |
| tx = (tx-0.5)/((1<<count)-1)+0.5f; | |
| ty = (ty-0.5)/((1<<count)-1)+0.5f; | |
| sx = sFPow(sx,1.0f/((1<<count)-1)); | |
| sy = sFPow(sy,1.0f/((1<<count)-1)); | |
| ca = (fade>>24)&0xff; | |
| cr = (fade>>16)&0xff; | |
| cg = (fade>> 8)&0xff; | |
| cb = (fade )&0xff; | |
| } | |
| else | |
| { | |
| i = 1; | |
| angle /= count; | |
| tx = (tx-0.5)/(count)+0.5f; | |
| ty = (ty-0.5)/(count)+0.5f; | |
| sx = sFPow(sx,1.0f/count); | |
| sy = sFPow(sy,1.0f/count); | |
| } | |
| sx *= sgnx; | |
| sy *= sgny; | |
| while(count>0) | |
| { | |
| count--; | |
| if(mode&16) | |
| { | |
| if(fade!=0xffffffff) | |
| { | |
| bm = Bitmap_Color(bm,0,fade); | |
| ca = (ca*ca)>>8; | |
| cr = (cr*cr)>>8; | |
| cg = (cg*cg)>>8; | |
| cb = (cb*cb)>>8; | |
| fade = (ca<<24)|(cr<<16)|(cg<<8)|(cb); | |
| } | |
| bm = Bitmap_Rotate(bm,angle,sx,sy,tx,ty,border,0,0); | |
| bm = Bitmap_Merge(mode&15,2,bm,bb); | |
| bb = (GenBitmap *) bm->Copy(); | |
| angle = angle*2; | |
| tx = (tx-0.5f)*2+0.5f; | |
| ty = (ty-0.5f)*2+0.5f; | |
| sx = sx*sx; | |
| sy = sy*sy; | |
| // bm->AddRef(); | |
| // bb = Bitmap_Merge(,mode&15,2,bb,bm); | |
| } | |
| else | |
| { | |
| if(fade!=0xffffffff) | |
| bm = Bitmap_Color(bm,0,fade); | |
| bm->AddRef(); | |
| bx = Bitmap_Rotate(bm,angle*i,(sx-1)*i+1,(sy-1)*i+1,(tx-0.5)*i+0.5,(ty-0.5)*i+0.5,border,0,0); | |
| if(!bx) | |
| bm->Release(); | |
| bb = Bitmap_Merge(mode&15,2,bb,bx); | |
| i++; | |
| } | |
| } | |
| bm->Release(); | |
| return bb; | |
| } | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Distort(GenBitmap *bb,GenBitmap *bm,sF32 dist,sInt border) | |
| { | |
| NOTEXTURES2(bb,bm); | |
| GenBitmap *in; | |
| sInt x,y; | |
| sU16 *t,*d,*a; | |
| sInt xs,ys; | |
| sInt u,v; | |
| sInt bumpx,bumpy; | |
| BilinearContext ctx; | |
| SCRIPTVERIFY(bb); | |
| SCRIPTVERIFY(bm); | |
| SCRIPTVERIFY(bb->ClassId==KC_BITMAP); | |
| SCRIPTVERIFY(bm->ClassId==KC_BITMAP); | |
| SCRIPTVERIFY(bm->Size==bb->Size); | |
| if(CheckBitmap(bm,&in)) return 0; | |
| bb->Release(); | |
| // prepare | |
| t = (sU16 *)bm->Data; | |
| d = (sU16 *)bb->Data; | |
| a = (sU16 *)in->Data; | |
| xs = in->XSize; | |
| ys = in->YSize; | |
| bumpx = (dist*xs)*4; | |
| bumpy = (dist*ys)*4; | |
| BilinearSetup(&ctx,(sU64 *)d,xs,ys,border); | |
| // rotate | |
| for(y=0;y<ys;y++) | |
| { | |
| for(x=0;x<xs;x++) | |
| { | |
| u = ((x)<<16) + ((a[0]-0x4000)*bumpx); | |
| v = ((y)<<16) + ((a[1]-0x4000)*bumpy); | |
| BilinearFilter(&ctx,(sU64 *)t,u,v); | |
| //BilinearFilter((sU64*)t,(sU64*)d,xs,ys,u,v,border); | |
| t+=4; | |
| a+=4; | |
| } | |
| } | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| static sInt filterbump(sU16 *s,sInt pos,sInt mask,sInt step) | |
| { | |
| return s[(pos-step-step)&mask]*1 | |
| + s[(pos-step )&mask]*3 | |
| - s[(pos )&mask]*3 | |
| - s[(pos+step )&mask]*1; | |
| } | |
| static sInt filterbumpsharp(sU16 *s,sInt pos,sInt mask,sInt step) | |
| { | |
| return 4*(s[(pos-step)&mask] - s[pos&mask]); | |
| } | |
| GenBitmap * __stdcall Bitmap_Normals(GenBitmap *bm,sF32 _dist,sInt mode) | |
| { | |
| NOTEXTURES1(bm); | |
| GenBitmap *in; | |
| sInt shiftx,shifty; | |
| sInt xs,ys; | |
| sInt x,y; | |
| //sU64 *mem; | |
| sU16 *sx,*sy,*s,*d; | |
| sInt vx,vy,vz; | |
| sF32 e; | |
| sInt dist; | |
| if(CheckBitmap(bm,&in)) return 0; | |
| dist = sFtol(_dist*65536.0f); | |
| d = (sU16 *) bm->Data; | |
| sx = sy = s = (sU16*) in->Data; | |
| xs = in->XSize; | |
| ys = in->YSize; | |
| shiftx = sGetPower2(in->XSize); | |
| shifty = sGetPower2(in->YSize); | |
| // Bitmap_Inner(bm->Data,0,bm->Size,8); // gray bitmap | |
| for(y=0;y<ys;y++) | |
| { | |
| sy = s; | |
| for(x=0;x<xs;x++) | |
| { | |
| if(mode&4) | |
| { | |
| vx = filterbumpsharp(sx,x*4,(xs-1)*4,4); | |
| vy = filterbumpsharp(sy,y*xs*4,(ys-1)*xs*4,xs*4); | |
| } | |
| else | |
| { | |
| vx = filterbump(sx,x*4,(xs-1)*4,4); | |
| vy = filterbump(sy,y*xs*4,(ys-1)*xs*4,xs*4); | |
| } | |
| /* | |
| vx = sx[((x-2)&(xs-1))*4]*1 | |
| + sx[((x-1)&(xs-1))*4]*3 | |
| - sx[((x )&(xs-1))*4]*3 | |
| - sx[((x+1)&(xs-1))*4]*1; | |
| vy = sy[((y-2)&(ys-1))*xs*4]*1 | |
| + sy[((y-1)&(ys-1))*xs*4]*3 | |
| - sy[((y )&(ys-1))*xs*4]*3 | |
| - sy[((y+1)&(ys-1))*xs*4]*1; | |
| */ | |
| vx = sRange7fff((((vx) * (dist>>4))>>(20-shiftx))+0x4000)-0x4000; | |
| vy = sRange7fff((((vy) * (dist>>4))>>(20-shifty))+0x4000)-0x4000; | |
| vz = 0; | |
| if(mode&1) | |
| { | |
| vz = (0x3fff*0x3fff)-vx*vx-vy*vy; | |
| if(vz>0) | |
| { | |
| // vz = sFSqrt(vz/16384.0f/16384.0f)*0x3fff; | |
| vz = sFSqrt(vz); | |
| } | |
| else | |
| { | |
| e = sFInvSqrt(vx*vx+vy*vy)*0x3fff; | |
| vx *= e; | |
| vy *= e; | |
| vz = 0; | |
| } | |
| } | |
| if(mode&2) | |
| { | |
| sSwap(vx,vy); | |
| vy=-vy; | |
| } | |
| d[0] = vx+0x4000; | |
| d[1] = vy+0x4000; | |
| d[2] = vz+0x4000; | |
| d[3] = 0xffff; | |
| d += 4; | |
| sy += 4; | |
| } | |
| sx += xs*4; | |
| } | |
| /*delete[] bm->Data; | |
| bm->Data = mem;*/ | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| void BumpLight(GenBitmap *bm,GenBitmap *bb,sS32 *para); | |
| GenBitmap * __stdcall Bitmap_Light(GenBitmap *bm,sInt subcode,sF32 px,sF32 py,sF32 pz,sF32 da,sF32 db, | |
| sU32 diff,sU32 ambi,sF32 outer,sF32 falloff,sF32 amp) | |
| { | |
| return Bitmap_Bump(bm,0,subcode,px,py,pz,da,db,diff,ambi,outer,falloff,amp,ambi,0,0); | |
| } | |
| GenBitmap * __stdcall Bitmap_Bump(GenBitmap *bm,GenBitmap *bb,sInt subcode,sF32 px,sF32 py,sF32 pz,sF32 da,sF32 db, | |
| sU32 _diff,sU32 _ambi,sF32 outer,sF32 falloff,sF32 amp, | |
| sU32 _spec,sF32 spow,sF32 samp) | |
| { | |
| NOTEXTURES2(bm,bb); | |
| GenBitmap *in; | |
| sInt xs,ys; | |
| sInt x,y; | |
| sU16 *d,*b,*s; | |
| sInt i; | |
| sU16 diff[4]; | |
| sU16 ambi[4]; | |
| sU16 spec[4]; | |
| sU16 buff[4]; | |
| sF32 dx,dy,dz; // spot direction | |
| sF32 e; | |
| sF32 f0; | |
| sF32 lx,ly,lz; // light -> material | |
| sF32 nx,ny,nz; // material normal | |
| sF32 hx,hy,hz; // halfway vector (specular) | |
| sF32 df; // spot direction factor | |
| sF32 lf; // light factor | |
| sF32 sf; // specular factor | |
| SCRIPTVERIFY(outer!=0); | |
| #if !sINTRO | |
| if(bm && bb) | |
| { | |
| SCRIPTVERIFY(bm->ClassId==KC_BITMAP); | |
| SCRIPTVERIFY(bb->ClassId==KC_BITMAP); | |
| SCRIPTVERIFY(bm->XSize==bb->XSize && bm->YSize==bb->YSize); | |
| } | |
| #endif | |
| if(CheckBitmap(bm,&in)) return 0; | |
| xs = in->XSize; | |
| ys = in->YSize; | |
| *(sU64 *)diff = GetColor64(_diff); | |
| *(sU64 *)ambi = GetColor64(_ambi); | |
| *(sU64 *)spec = GetColor64(_spec); | |
| px = px*xs*2-(xs/2); | |
| py = py*ys*2-(ys/2); | |
| pz = pz*xs; | |
| da *= sPI2F; | |
| db *= sPIF; | |
| dx = dy = sFCos(db); | |
| dx *= sFSin(da); | |
| dy *= sFCos(da); | |
| dz = sFSin(db); | |
| s = (sU16 *)in->Data; | |
| d = (sU16 *)bm->Data; | |
| if(bb) | |
| { | |
| b = (sU16 *)bb->Data; | |
| } | |
| else | |
| { | |
| b = 0; | |
| } | |
| lf = 1.0f; | |
| sf = 0.0f; | |
| df = 1.0f; | |
| nx = 0; | |
| ny = 0; | |
| nz = 1; | |
| lx = dx; | |
| ly = dy; | |
| lz = dz; | |
| if(subcode==0) | |
| { | |
| px = px-dx*pz/dz; | |
| py = py-dy*pz/dz; | |
| } | |
| samp *= 65536.0f; | |
| for(y=0;y<bm->YSize;y++) | |
| { | |
| for(x=0;x<bm->XSize;x++) | |
| { | |
| if(subcode!=2) | |
| { | |
| lx = x-px; | |
| ly = y-py; | |
| lz = pz; | |
| e = 1/sFSqrt(lx*lx+ly*ly+lz*lz); | |
| lx*=e; | |
| ly*=e; | |
| lz*=e; | |
| } | |
| if(b) | |
| { | |
| nx = (b[0]-0x4000)/16384.0f; | |
| ny = (b[1]-0x4000)/16384.0f; | |
| nz = (b[2]-0x4000)/16384.0f; | |
| b+=4; | |
| } | |
| lf = lx*nx+ly*ny+lz*nz; | |
| if(samp) | |
| { | |
| hx = lx; | |
| hy = ly; | |
| hz = lz+1; | |
| e = 1/sFSqrt(hx*hx+hy*hy+hz*hz); | |
| sf = hx*nx+hy*ny+hz*nz; | |
| if(sf<0) sf=0; | |
| sf = sFPow(sf*e,spow); | |
| } | |
| if(subcode==0) | |
| { | |
| df = (lx*dx+ly*dy+lz*dz); | |
| if(df<outer) | |
| df = 0; | |
| else | |
| df = sFPow((df-outer)/(1-outer),falloff); | |
| } | |
| f0 = df*lf*amp; | |
| for(i=0;i<4;i++) | |
| buff[i] = sRange7fff(sFtol(s[i]*(ambi[i]+diff[i]*f0)/0x8000)); | |
| AddScale64(*(sU64 *)d,*(sU64 *)buff,*(sU64 *)spec,sFtol(df*sf*samp)); | |
| s+=4; | |
| d+=4; | |
| } | |
| } | |
| if(bb) bb->Release(); | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| struct letterz | |
| { | |
| sU16 xp,yp; | |
| sS16 w0,w1,w2; | |
| }; | |
| GenBitmap * __stdcall Bitmap_Text(KOp *op,KEnvironment *kenv,GenBitmap *bm,sF32 x,sF32 y,sF32 width,sF32 height,sU32 col,sU32 flags,sInt extspace,sF32 inspace,sF32 lineskip,sChar *text,sChar *font) | |
| { | |
| NOTEXTURES1(bm); | |
| sU64 col64; | |
| col64 = GetColor64(col); | |
| sU32 *bitmem; | |
| sInt size; | |
| sU8 *data; | |
| static letterz let[256]; | |
| GenBitmap *in; | |
| sInt xi,yi,i; | |
| sU32 fade; | |
| sInt xs,ys,xp,yp,yf,is,es,xp0,lsk; | |
| sU32 *s; | |
| #if !sINTRO | |
| sInt w0,w1,w2; | |
| sInt count,chr; | |
| sInt page; | |
| sInt widths[3]; | |
| #endif | |
| //const sInt alias = 2; | |
| const sInt alias = 4; | |
| if(CheckBitmap(bm,&in)) return 0; | |
| sSetMem(let,0,sizeof(let)); | |
| // write let for normal character generation | |
| // read let after all is done | |
| // eventually write blob | |
| // maybe it's better to write blob everytime, just not always store it. (shorter cleaner code) | |
| xs = bm->XSize*alias; | |
| ys = bm->YSize*alias; | |
| es = extspace*alias; | |
| es += 2*alias; | |
| is = inspace*xs; | |
| xp = x*xs+es; | |
| yp = y*ys+es; | |
| data = (sU8*)op->GetBlob(size); | |
| #if !sINTRO | |
| page = (flags&0x70)>>4; | |
| if((flags&0x80) && data && data[0]==3 && data[1]==(page!=0) && | |
| *((sU16 *)(data+2))==bm->XSize && *((sU16 *)(data+4))==bm->YSize) | |
| { | |
| yf = *((sU16 *)(data+6)); | |
| data+=8; | |
| if(page) | |
| { | |
| for(i=0;i<256;i++) | |
| { | |
| let[i].xp = *((sU16 *)data); data+=2; | |
| let[i].yp = *((sU16 *)data); data+=2; | |
| let[i].w0 = *((sS16 *)data); data+=2; | |
| let[i].w1 = *((sS16 *)data); data+=2; | |
| let[i].w2 = *((sS16 *)data); data+=2; | |
| } | |
| } | |
| for(i=0;i<bm->Size;i++) | |
| { | |
| fade = *data++; | |
| fade = (fade<<5) | (fade<<2) | (fade>>1); | |
| fade = (fade)|(fade<<8); | |
| Fade64(bm->Data[i],in->Data[i],col64,fade); | |
| } | |
| } | |
| else | |
| #endif | |
| { | |
| op->SetBlob(0,0); | |
| yf = sSystem->FontBegin(xs,ys,font,xs*height,ys*width,4); | |
| lsk = lineskip * yf; | |
| #if !sINTRO | |
| if(page) // font mode | |
| { | |
| count = 0; | |
| chr = 'a'; | |
| sSetMem(kenv->Letters[page],0,sizeof(KLetterMetric)*256); | |
| while(*text || chr<count) | |
| { | |
| if(text[0]=='-' && text[1]!='-' && text[1]!=0) | |
| { | |
| text++; | |
| count = (*text++)&255; | |
| } | |
| if(text[0]=='-' && text[1]=='-') | |
| { | |
| text++; | |
| } | |
| if(chr<count) | |
| { | |
| chr++; | |
| } | |
| else | |
| { | |
| count = 0; | |
| chr = (*text++)&255; | |
| } | |
| sSystem->FontCharWidth(chr,widths); | |
| w1 = widths[1]; | |
| //xf = sAbs(widths[0]) + sAbs(widths[1]) + sAbs(widths[2]); | |
| if(xp+w1+es+2*is>=xs) | |
| { | |
| yp = sAlign(yp+yf+2*is,alias); | |
| yp += es; | |
| xp = x*xs+es; | |
| if(yp+yf+es+2*is>=ys) | |
| break; | |
| } | |
| let[chr].xp = xp; | |
| let[chr].yp = yp; | |
| let[chr].w0 = widths[0]; | |
| let[chr].w1 = widths[1]; | |
| let[chr].w2 = widths[2]; | |
| sChar c=chr; | |
| sSystem->FontPrint(xp+is-widths[0],yp+is,&c,1); | |
| xp = sAlign(xp+w1+2*is,alias); | |
| xp += es; | |
| } | |
| } | |
| else // normal mode | |
| #endif | |
| { | |
| sInt lf = 0; | |
| for(i=0;text[i];i++) | |
| if(text[i]=='\n') lf++; | |
| if(flags&2) | |
| yp -= yf*(lf+1)/2; | |
| while(*text) | |
| { | |
| for(i=0;text[i] && text[i]!='\n';i++) ; | |
| if(i>0) | |
| { | |
| if(flags&1) | |
| xp0 = xp-sSystem->FontWidth((sChar *)text,i)/2; | |
| else | |
| xp0 = xp; | |
| sSystem->FontPrint(xp0,yp,(sChar *)text,i); | |
| } | |
| text+=i; | |
| if(*text=='\n') | |
| { | |
| yp += lsk; | |
| text++; | |
| } | |
| } | |
| } | |
| // write to bitmap | |
| bitmem = sSystem->FontBitmap(); | |
| i = 0; | |
| for(yi=0;yi<bm->YSize;yi++) | |
| { | |
| s = bitmem+yi*xs*alias; | |
| for(xi=0;xi<bm->XSize;xi++) | |
| { | |
| if(alias==1) | |
| fade = s[0]&255; | |
| if(alias==2) | |
| fade = ((s[0]&255)+(s[1]&255)+(s[0+xs]&255)+(s[1+xs]&255))>>2; | |
| if(alias==4) | |
| fade = ((s[0+0*xs]&255)+(s[1+0*xs]&255)+(s[2+0*xs]&255)+(s[3+0*xs]&255) | |
| +(s[0+1*xs]&255)+(s[1+1*xs]&255)+(s[2+1*xs]&255)+(s[3+1*xs]&255) | |
| +(s[0+2*xs]&255)+(s[1+2*xs]&255)+(s[2+2*xs]&255)+(s[3+2*xs]&255) | |
| +(s[0+3*xs]&255)+(s[1+3*xs]&255)+(s[2+3*xs]&255)+(s[3+3*xs]&255))>>4; | |
| fade = (fade)|(fade<<8); | |
| Fade64(bm->Data[i],in->Data[i],col64,fade); | |
| i++; | |
| s+=alias; | |
| } | |
| } | |
| // write to blob | |
| #if !sPLAYER | |
| if(flags&0x80) | |
| { | |
| sU8 *mem; | |
| size = 8 + bm->XSize*bm->YSize; | |
| if(page) | |
| size += 256*10; | |
| mem = data = new sU8[size]; | |
| data[0] = 3; | |
| data[1] = page != 0; | |
| *((sU16 *)(data+2)) = bm->XSize; | |
| *((sU16 *)(data+4)) = bm->YSize; | |
| *((sU16 *)(data+6)) = yf; | |
| data+=8; | |
| if(page) | |
| { | |
| for(i=0;i<256;i++) | |
| { | |
| *((sU16 *)data) = let[i].xp; data+=2; | |
| *((sU16 *)data) = let[i].yp; data+=2; | |
| *((sS16 *)data) = let[i].w0; data+=2; | |
| *((sS16 *)data) = let[i].w1; data+=2; | |
| *((sS16 *)data) = let[i].w2; data+=2; | |
| } | |
| } | |
| for(yi=0;yi<bm->YSize;yi++) | |
| { | |
| s = bitmem+yi*xs*alias; | |
| for(xi=0;xi<bm->XSize;xi++) | |
| { | |
| if(alias==1) | |
| fade = s[0]&255; | |
| if(alias==2) | |
| fade = ((s[0]&255)+(s[1]&255)+(s[0+xs]&255)+(s[1+xs]&255))>>2; | |
| if(alias==4) | |
| fade = ((s[0+0*xs]&255)+(s[1+0*xs]&255)+(s[2+0*xs]&255)+(s[3+0*xs]&255) | |
| +(s[0+1*xs]&255)+(s[1+1*xs]&255)+(s[2+1*xs]&255)+(s[3+1*xs]&255) | |
| +(s[0+2*xs]&255)+(s[1+2*xs]&255)+(s[2+2*xs]&255)+(s[3+2*xs]&255) | |
| +(s[0+3*xs]&255)+(s[1+3*xs]&255)+(s[2+3*xs]&255)+(s[3+3*xs]&255))>>4; | |
| *data++ = fade>>5; | |
| s+=alias; | |
| } | |
| } | |
| op->SetBlob(mem,size); | |
| } | |
| #endif | |
| sSystem->FontEnd(); | |
| } | |
| #if !sINTRO | |
| if(page) | |
| { | |
| for(i=0;i<256;i++) | |
| { | |
| xp = let[i].xp; | |
| yp = let[i].yp; | |
| w0 = let[i].w0; | |
| w1 = let[i].w1; | |
| w2 = let[i].w2; | |
| // if(w0|w1|w2) sDPrintF("'%c' %08x %08x %08x %08x %08x\n",i,xp,yp,w0,w1,w2); | |
| kenv->Letters[page][i].UV.x0 = xp*1.0f/(xs); | |
| kenv->Letters[page][i].UV.y0 = yp*1.0f/(ys); | |
| kenv->Letters[page][i].UV.x1 = (xp+w1+is*2)*1.0f/(xs); | |
| kenv->Letters[page][i].UV.y1 = (yp+yf+is*2)*1.0f/(ys); | |
| kenv->Letters[page][i].PreSpace = (w0-is)*1.0f/xs; | |
| kenv->Letters[page][i].Width = (w0+w1+w2+is*2)*1.0f/xs; | |
| } | |
| sDPrintF("-----------------------------------------\n"); | |
| } | |
| #endif | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| static sF32 noise2(sInt x,sInt y,sInt mask,sInt seed) | |
| { | |
| sInt v00,v01,v10,v11,vx,vy; | |
| sF32 f00,f01,f10,f11; | |
| sF32 tx,ty,fa,fb,f; | |
| mask &= 255; | |
| vx = (x>>16) & mask; tx=(x&0xffff)/65536.0f; | |
| vy = (y>>16) & mask; ty=(y&0xffff)/65536.0f; | |
| v00 = sPerlinPermute[((vx+0) )+sPerlinPermute[((vy+0) )^seed]]; | |
| v01 = sPerlinPermute[((vx+1)&mask)+sPerlinPermute[((vy+0) )^seed]]; | |
| v10 = sPerlinPermute[((vx+0) )+sPerlinPermute[((vy+1)&mask)^seed]]; | |
| v11 = sPerlinPermute[((vx+1)&mask)+sPerlinPermute[((vy+1)&mask)^seed]]; | |
| f00 = sPerlinRandom[v00][0]*(tx-0)+sPerlinRandom[v00][1]*(ty-0); | |
| f01 = sPerlinRandom[v01][0]*(tx-1)+sPerlinRandom[v01][1]*(ty-0); | |
| f10 = sPerlinRandom[v10][0]*(tx-0)+sPerlinRandom[v10][1]*(ty-1); | |
| f11 = sPerlinRandom[v11][0]*(tx-1)+sPerlinRandom[v11][1]*(ty-1); | |
| tx = tx*tx*tx*(10+tx*(6*tx-15)); | |
| ty = ty*ty*ty*(10+ty*(6*ty-15)); | |
| //tx = tx*tx*(3-2*tx); | |
| //ty = ty*ty*(3-2*ty); | |
| fa = f00+(f01-f00)*tx; | |
| fb = f10+(f11-f10)*tx; | |
| f = fa+(fb-fa)*ty; | |
| return f; | |
| } | |
| GenBitmap * __stdcall Bitmap_Perlin(sInt xs,sInt ys,sInt freq,sInt oct,sF32 fadeoff,sInt seed,sInt mode,sF32 amp,sF32 gamma,sU32 col0,sU32 col1) | |
| { | |
| NOTEXTURES0(); | |
| GenBitmap *bm; | |
| sInt i; | |
| sInt x,y,noffs; | |
| sInt shiftx,shifty; | |
| sU64 c0,c1; | |
| sU64 *tile; | |
| bm = NewBitmap(xs,ys); | |
| c0 = GetColor64(col0); | |
| c1 = GetColor64(col1); | |
| shiftx = 16-sGetPower2(bm->XSize); | |
| shifty = 16-sGetPower2(bm->YSize); | |
| tile = bm->Data; | |
| seed &= 255; | |
| mode &= 3; | |
| for(i=0;i<1025;i++) | |
| GammaTable[i] = sRange7fff(sFPow(i/1024.0f,gamma)*0x8000)*2; | |
| if(mode & 1) | |
| { | |
| amp *= 0x8000; | |
| noffs = 0; | |
| } | |
| else | |
| { | |
| amp *= 0x4000; | |
| noffs = 0x4000; | |
| } | |
| sInt ampi = sFtol(amp); | |
| sInt sinTab[257]; | |
| if(mode & 2) | |
| { | |
| for(x=0;x<257;x++) | |
| sinTab[x] = sFtol(sFSin(sPI2F * x / 256.0f) * 0.5f * 65536.0f); | |
| } | |
| #if !sINTRO | |
| sInt *nrow = new sInt[bm->XSize]; | |
| sInt *poly = new sInt[bm->XSize>>freq]; | |
| for(x=0;x<(bm->XSize>>freq);x++) | |
| { | |
| sF32 f = 1.0f * x / (bm->XSize>>freq); | |
| poly[x] = sFtol(f*f*f*(10+f*(6*f-15))*16384.0f); | |
| } | |
| for(y=0;y<bm->YSize;y++) | |
| { | |
| sSetMem(nrow,0,sizeof(sInt)*bm->XSize); | |
| sF32 s = 1.0f; | |
| // make some noise | |
| for(i=freq;i<freq+oct;i++) | |
| { | |
| sInt xGrpSize = (shiftx+i < 16) ? sMin(bm->XSize,1<<(16-shiftx-i)) : 1; | |
| sInt groups = (shiftx+i < 16) ? bm->XSize>>(16-shiftx-i) : bm->XSize; | |
| sInt mask = ((1<<i)-1) & 255; | |
| sInt py = y<<(shifty+i); | |
| sInt vy = (py >> 16) & mask; | |
| sInt dtx = 1 << (shiftx+i); | |
| sF32 ty = (py & 0xffff) / 65536.0f; | |
| sF32 tyf = ty*ty*ty*(10+ty*(6*ty-15)); | |
| sF32 ty0f = ty*(1-tyf); | |
| sF32 ty1f = (ty-1)*tyf; | |
| sInt vy0 = sPerlinPermute[((vy+0) )^seed]; | |
| sInt vy1 = sPerlinPermute[((vy+1)&mask)^seed]; | |
| sInt shf = i-freq; | |
| sInt si = sFtol(s * 16384.0f); | |
| if(shiftx+i < 16 || (py & 0xffff)) // otherwise, the contribution is always zero | |
| { | |
| sInt *rowp = nrow; | |
| for(sInt vx=0;vx<groups;vx++) | |
| { | |
| sInt v00 = sPerlinPermute[((vx+0)&mask)+vy0]; | |
| sInt v01 = sPerlinPermute[((vx+1)&mask)+vy0]; | |
| sInt v10 = sPerlinPermute[((vx+0)&mask)+vy1]; | |
| sInt v11 = sPerlinPermute[((vx+1)&mask)+vy1]; | |
| sF32 f_0h = sPerlinRandom[v00][0] + (sPerlinRandom[v10][0] - sPerlinRandom[v00][0]) * tyf; | |
| sF32 f_1h = sPerlinRandom[v01][0] + (sPerlinRandom[v11][0] - sPerlinRandom[v01][0]) * tyf; | |
| sF32 f_0v = sPerlinRandom[v00][1]*ty0f + sPerlinRandom[v10][1]*ty1f; | |
| sF32 f_1v = sPerlinRandom[v01][1]*ty0f + sPerlinRandom[v11][1]*ty1f; | |
| sInt fa = sFtol(f_0v * 65536.0f); | |
| sInt fb = sFtol((f_1v - f_1h) * 65536.0f); | |
| sInt fad = sFtol(f_0h * dtx); | |
| sInt fbd = sFtol(f_1h * dtx); | |
| for(sInt xg=0;xg<xGrpSize;xg++) | |
| { | |
| sInt nni = fa + (((fb-fa)*poly[xg<<shf])>>14); | |
| switch(mode) | |
| { | |
| case 0: break; | |
| case 1: nni = sAbs(nni); break; | |
| case 3: nni &= 0x7fff; | |
| case 2: | |
| { | |
| sInt ind = (nni>>8) & 0xff; | |
| nni = sinTab[ind] + (((sinTab[ind+1] - sinTab[ind]) * (nni & 0xff)) >> 8); | |
| } | |
| break; | |
| default: __assume(false); break; | |
| } | |
| *rowp++ += (nni*si)>>14; | |
| fa += fad; | |
| fb += fbd; | |
| } | |
| } | |
| } | |
| s *= fadeoff; | |
| } | |
| // resolve | |
| for(x=0;x<bm->XSize;x++) | |
| Fade64(*tile++,c0,c1,GetGamma(sRange7fff(sMulShift(nrow[x],ampi)+noffs))); | |
| } | |
| delete[] nrow; | |
| delete[] poly; | |
| #else | |
| for(y=0;y<bm->YSize;y++) | |
| { | |
| for(x=0;x<bm->XSize;x++) | |
| { | |
| sInt val; | |
| sF32 n = 0.0f, s = 1.0f; | |
| for(i=freq;i<freq+oct;i++) | |
| { | |
| sInt px = ((x)<<(16-shiftx))<<i; | |
| sInt py = ((y)<<(16-shifty))<<i; | |
| sF32 nn = noise2(px,py,((1<<i)-1),seed); | |
| if(mode&1) | |
| nn = sFAbs(nn); | |
| if(mode&2) | |
| nn = sFSin(nn*sPI2F)*0.5f; | |
| n += nn*s; | |
| s*=fadeoff; | |
| } | |
| /*if(mode&1) | |
| n = sFPow(n*amp,gamma); | |
| else | |
| n = sFPow(n*amp*0.5f+0.5f,gamma); | |
| val = sRange7fff(n*0x8000)*2;*/ | |
| val = sRange7fff(sFtol(n*amp)+noffs); | |
| val = GetGamma(val); | |
| Fade64(*tile,c0,c1,val); | |
| tile++; | |
| } | |
| } | |
| #endif | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Cell(sInt xs,sInt ys,sU32 col0,sU32 col1,sU32 col2,sInt max,sInt seed,sF32 amp,sF32 gamma,sInt mode,sF32 mindistf,sInt percent,sF32 aspect) | |
| { | |
| NOTEXTURES0(); | |
| GenBitmap *bm; | |
| static sInt cells[256][3]; | |
| static sInt cellt[256]; | |
| sInt x,y,i,j,dist,best,best2,besti,best2i; | |
| sInt dx,dy,px,py; | |
| sInt shiftx,shifty; | |
| sF32 v0,v1; | |
| sInt val,mdist; | |
| sU64 c0,c1,cc,cb; | |
| sU64 *tile; | |
| sBool cut; | |
| SCRIPTVERIFY(max>=1 && max<=256); | |
| bm = NewBitmap(xs,ys); | |
| sSetRndSeed(seed); | |
| for(i=0;i<max*3;i++) | |
| cells[0][i] = sGetRnd(0x4000); | |
| mdist = sFtol(mindistf*0x4000); | |
| mdist = mdist*mdist; | |
| for(i=1;i<max;) | |
| { | |
| if((mode&2) && (sInt)sGetRnd(255)<percent) | |
| cells[i][2] = 0xffff; | |
| px = ((cells[i][0])&0x3fff)-0x2000; | |
| py = ((cells[i][1])&0x3fff)-0x2000; | |
| cut = sFALSE; | |
| for(j=0;j<i && !cut;j++) | |
| { | |
| dx = ((cells[j][0]-px)&0x3fff)-0x2000; | |
| dy = ((cells[j][1]-py)&0x3fff)-0x2000; | |
| dist = dx*dx+dy*dy; | |
| if(dist<mdist) | |
| { | |
| cut = sTRUE; | |
| } | |
| } | |
| if(cut) | |
| { | |
| max--; | |
| cells[i][0] = cells[max][0]; | |
| cells[i][1] = cells[max][1]; | |
| cells[i][2] = cells[max][2]; | |
| } | |
| else | |
| { | |
| i++; | |
| } | |
| } | |
| shiftx = 14-sGetPower2(bm->XSize); | |
| shifty = 14-sGetPower2(bm->YSize); | |
| c0 = GetColor64(col1); | |
| c1 = GetColor64(col0); | |
| cb = GetColor64(col2); | |
| tile = bm->Data; | |
| aspect = sFPow(2,aspect); | |
| sF32 aspdiv; | |
| #if !sINTRO | |
| sInt aspf; | |
| sBool flipxy; | |
| if(aspect >= 1.0f) | |
| { | |
| aspf = 65536 / (aspect * aspect); | |
| aspdiv = aspect / 16384.0f; | |
| flipxy = sFALSE; | |
| } | |
| else | |
| { | |
| aspf = aspect * aspect * 65536; | |
| aspdiv = 1.0f / (16384.0f * aspect); | |
| flipxy = sTRUE; | |
| } | |
| if(flipxy) | |
| { | |
| for(i=0;i<max;i++) | |
| sSwap(cells[i][0],cells[i][1]); | |
| } | |
| static const int tileSize = 16; | |
| for(sInt by=0;by<bm->YSize;by+=tileSize) | |
| { | |
| for(sInt bx=0;bx<bm->XSize;bx+=tileSize) | |
| { | |
| // for all cells, calc distance lower bound | |
| sInt px0 = bx << shiftx, px1 = (bx+tileSize-1) << shiftx; | |
| sInt py0 = by << shifty, py1 = (by+tileSize-1) << shifty; | |
| if(flipxy) | |
| { | |
| sSwap(px0,py0); | |
| sSwap(px1,py1); | |
| } | |
| for(i=0;i<max;i++) | |
| { | |
| dx = ((cells[i][0]-px0)&0x3fff)-0x2000; | |
| dy = ((cells[i][0]-px1)&0x3fff)-0x2000; | |
| if((dx ^ dy) <= 0) | |
| cellt[i] = 0; | |
| else | |
| { | |
| dx = sMin(sAbs(dx),sAbs(dy)); | |
| cellt[i] = sMulShift(dx*dx,aspf); | |
| } | |
| dx = ((cells[i][1]-py0)&0x3fff)-0x2000; | |
| dy = ((cells[i][1]-py1)&0x3fff)-0x2000; | |
| if((dx ^ dy) > 0) | |
| { | |
| dy = sMin(sAbs(dx),sAbs(dy)); | |
| cellt[i] += dy*dy; | |
| } | |
| } | |
| // (insertion) sort by it | |
| for(i=1;i<max;i++) | |
| { | |
| sInt x = cells[i][0], y = cells[i][1], c = cells[i][2]; | |
| sInt dy = cellt[i], j = i; | |
| while(j && cellt[j-1] > dy) | |
| { | |
| cells[j][0] = cells[j-1][0]; | |
| cells[j][1] = cells[j-1][1]; | |
| cells[j][2] = cells[j-1][2]; | |
| cellt[j] = cellt[j-1]; | |
| j--; | |
| } | |
| cells[j][0] = x; | |
| cells[j][1] = y; | |
| cells[j][2] = c; | |
| cellt[j] = dy; | |
| } | |
| // render tile | |
| tile = bm->Data + by*bm->XSize + bx; | |
| for(sInt ty=0;ty<tileSize;ty++) | |
| { | |
| py = (by+ty) << shifty; | |
| for(sInt tx=0;tx<tileSize;tx++) | |
| { | |
| px = (bx+tx) << shiftx; | |
| if(flipxy) | |
| x = py, y = px; | |
| else | |
| x = px, y = py; | |
| best = 0x8000*0x8000; | |
| best2 = 0x8000*0x8000; | |
| besti = best2i = -1; | |
| // search for points | |
| for(sInt i=0;i<max && best2 > cellt[i];i++) | |
| { | |
| dx = ((cells[i][0]-x)&0x3fff)-0x2000; | |
| dy = ((cells[i][1]-y)&0x3fff)-0x2000; | |
| dist = sMulShift(dx*dx,aspf) + dy*dy; | |
| if(dist<best) | |
| { | |
| best2 = best; | |
| best2i = besti; | |
| best = dist; | |
| besti = i; | |
| } | |
| else if(dist>best && dist<best2) | |
| { | |
| best2 = dist; | |
| best2i = i; | |
| } | |
| } | |
| v0 = sFSqrt(best) * aspdiv; | |
| if(mode&1) | |
| { | |
| v1 = sFSqrt(best2) * aspdiv; | |
| if(v0+v1>0.00001f) | |
| v0 = (v1-v0)/(v1+v0); | |
| else | |
| v0 = 0; | |
| } | |
| val = sRange7fff(sFPow(v0*amp,gamma)*0x8000)*2; // the sFPow is the biggest individual CPU hog here | |
| if(mode&4) | |
| val = 0x10000-val; | |
| if(mode&2) | |
| { | |
| if(cells[besti][2]==0xffff) | |
| cc=cb; | |
| else | |
| Fade64(cc,c0,c1,cells[besti][2]*4); | |
| Fade64(*tile,cc,cb,val); | |
| } | |
| else | |
| { | |
| Fade64(*tile,c0,c1,val); | |
| } | |
| tile++; | |
| } | |
| tile += bm->XSize-tileSize; | |
| } | |
| } | |
| } | |
| #else | |
| sInt aspx,aspy; | |
| if(aspect >= 1.0f) | |
| { | |
| aspx = 65536 / (aspect * aspect); | |
| aspy = 65536; | |
| aspdiv = aspect / 16384.0f; | |
| } | |
| else | |
| { | |
| aspx = 65536; | |
| aspy = aspect * aspect * 65536; | |
| aspdiv = 1.0f / (16384.0f * aspect); | |
| } | |
| sInt searched = 0; | |
| for(y=0;y<bm->YSize;y++) | |
| { | |
| py = (y) << shifty; | |
| for(i=0;i<max;i++) | |
| { | |
| dy = ((cells[i][1]-py)&0x3fff)-0x2000; | |
| cellt[i] = sMulShift(dy*dy,aspy); | |
| } | |
| // (insertion) sort by y-distance | |
| for(i=1;i<max;i++) | |
| { | |
| sInt x = cells[i][0], y = cells[i][1]; | |
| sInt dy = cellt[i], j = i; | |
| while(j && cellt[j-1] > dy) | |
| { | |
| cells[j][0] = cells[j-1][0]; | |
| cells[j][1] = cells[j-1][1]; | |
| cellt[j] = cellt[j-1]; | |
| j--; | |
| } | |
| cells[j][0] = x; | |
| cells[j][1] = y; | |
| cellt[j] = dy; | |
| } | |
| best = 0x8000*0x8000; | |
| best2 = 0x8000*0x8000; | |
| besti = best2i = -1; | |
| for(x=0;x<bm->XSize;x++) | |
| { | |
| px = (x)<<(shiftx); | |
| // update "best point" | |
| if(besti != -1 && best2i != -1) | |
| { | |
| dx = ((cells[besti][0]-px)&0x3fff)-0x2000; | |
| best = sMulShift(dx*dx,aspx) + cellt[besti]; | |
| dx = ((cells[best2i][0]-px)&0x3fff)-0x2000; | |
| best2 = sMulShift(dx*dx,aspx) + cellt[best2i]; | |
| if(best2 < best) | |
| { | |
| sSwap(best,best2); | |
| sSwap(besti,best2i); | |
| } | |
| } | |
| // search for better points | |
| for(sInt i=0;i<max && best2 > cellt[i];i++) | |
| { | |
| searched++; | |
| dx = ((cells[i][0]-px)&0x3fff)-0x2000; | |
| dist = sMulShift(dx*dx,aspx) + cellt[i]; | |
| if(dist<best) | |
| { | |
| best2 = best; | |
| best2i = besti; | |
| best = dist; | |
| besti = i; | |
| } | |
| else if(dist>best && dist<best2) | |
| { | |
| best2 = dist; | |
| best2i = i; | |
| } | |
| } | |
| v0 = sFSqrt(best) * aspdiv; | |
| if(mode&1) | |
| { | |
| v1 = sFSqrt(best2) * aspdiv; | |
| if(v0+v1>0.00001f) | |
| v0 = (v1-v0)/(v1+v0); | |
| else | |
| v0 = 0; | |
| } | |
| val = sRange7fff(sFPow(v0*amp,gamma)*0x8000)*2; | |
| if(mode&4) | |
| val = 0x10000-val; | |
| if(mode&2) | |
| { | |
| if(cells[besti][2]==0xffff) | |
| cc=cb; | |
| else | |
| Fade64(cc,c0,c1,cells[besti][2]*4); | |
| Fade64(*tile,cc,cb,val); | |
| } | |
| else | |
| { | |
| Fade64(*tile,c0,c1,val); | |
| } | |
| tile++; | |
| } | |
| } | |
| #endif | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Gradient(sInt xs,sInt ys,sU32 col0,sU32 col1,sF32 posf,sF32 a,sF32 length,sInt mode) | |
| { | |
| NOTEXTURES0(); | |
| GenBitmap *bm; | |
| sU64 c0,c1; | |
| sInt c,cdx,cdy,x,y; | |
| sInt dx,dy,pos; | |
| sF32 l; | |
| sInt val; | |
| sU64 *tile; | |
| bm = NewBitmap(xs,ys); | |
| c0 = GetColor64(col0); | |
| c1 = GetColor64(col1); | |
| l = 32768.0f / length; | |
| pos = posf*32768.0f; | |
| dx = sFtol(sFCos(a * sPI2) * l); | |
| dy = sFtol(sFSin(a * sPI2) * l); | |
| cdx = sMulShift(dx,0x10000/bm->XSize); | |
| cdy = sMulShift(dy,0x10000/bm->YSize)-bm->XSize*cdx; | |
| c = 0x4000-(dx/2+dy/2)*(posf+1); | |
| tile = bm->Data; | |
| for(y=0;y<bm->YSize;y++) | |
| { | |
| for(x=0;x<bm->XSize;x++) | |
| { | |
| switch(mode) | |
| { | |
| case 0: | |
| val = sRange7fff(c)*2; | |
| break; | |
| case 1: | |
| val = sFtol(sFSin(sRange7fff(c)*sPI2/0x8000+0x2000)*0x7fff+0x7fff); | |
| break; | |
| case 2: | |
| val = sFtol(sFSin(sRange7fff(c)*sPI2/0x10000)*0xffff); | |
| break; | |
| } | |
| Fade64(*tile,c0,c1,val); | |
| c += cdx; | |
| tile++; | |
| } | |
| c += cdy; | |
| } | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Sharpen(GenBitmap *bm,sInt order,sF32 sx,sF32 sy,sF32 amp) | |
| { | |
| NOTEXTURES1(bm); | |
| GenBitmap *bx; | |
| sU64 color; | |
| SCRIPTVERIFY(bm); | |
| bx = bm; | |
| bx->AddRef(); | |
| if(CheckBitmap(bm)) return 0; | |
| color = sRange<sInt>(amp*0x800,0x7fff,-0x7fff)&0xffff; | |
| color |= color<<16; | |
| color |= color<<32; | |
| bm = Bitmap_Blur(bm,order|0x10,sx,sy,1.0f); | |
| Bitmap_Inner(bm->Data,&color,bm->Size,BI_SHARPEN,bx->Data); | |
| bx->Release(); | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Import(KOp *op,sChar *filename) | |
| { | |
| NOTEXTURES0(); | |
| GenBitmap *bm; | |
| const sU8 *data; | |
| sU32 *s; | |
| sU64 *d; | |
| sInt size; | |
| sInt xs,ys; | |
| sU8 *pic; | |
| bm = 0; | |
| data = op->GetBlob(size); | |
| #if !sPLAYER | |
| if(data==0) | |
| { | |
| data = sSystem->LoadFile(filename,size); | |
| op->SetBlob(data,size); | |
| } | |
| #endif | |
| if(data) | |
| { | |
| if(sSystem->LoadBitmapCore(data,size,xs,ys,pic)) | |
| { | |
| bm = new GenBitmap; | |
| sInt nxs = 1<<sFindLowerPower(xs); | |
| sInt nys = 1<<sFindLowerPower(ys); | |
| sDPrintF("load pic %dx%d -> %dx%d (%s)\n",xs,ys,nxs,nys,filename); | |
| bm->Init(nxs,nys); | |
| s = (sU32 *)pic; | |
| d = (sU64 *)bm->Data; | |
| for(sInt y=0;y<nys;y++) | |
| { | |
| for(sInt x=0;x<nxs;x++) | |
| { | |
| d[x] = GetColor64(s[x]); | |
| } | |
| d += nxs; | |
| s += xs; | |
| } | |
| delete[] pic; | |
| } | |
| } | |
| return bm; | |
| } | |
| GenBitmap * __stdcall Bitmap_Import2(KOp *op,sInt quality,sChar *filename) | |
| { | |
| NOTEXTURES0(); | |
| GenBitmap *bm = 0; | |
| const sU8 *data; | |
| sInt size; | |
| #if !sPLAYER || sLINK_FRIED | |
| sInt xs,ys; | |
| sU8 *pic; | |
| #endif | |
| data = op->GetBlob(size); | |
| #if !sPLAYER | |
| if(!data) | |
| { | |
| data = sSystem->LoadFile(filename,size); | |
| if(data && sSystem->LoadBitmapCore(data,size,xs,ys,pic)) | |
| { | |
| // convert to premultiplied alpha | |
| for(sInt i=0;i<xs*ys;i++) | |
| { | |
| sInt a = pic[i*4+3]+1; | |
| pic[i*4+0] = (pic[i*4+0] * a) >> 8; | |
| pic[i*4+1] = (pic[i*4+1] * a) >> 8; | |
| pic[i*4+2] = (pic[i*4+2] * a) >> 8; | |
| } | |
| sU8* friedBlob = SaveFRIED(pic,xs,ys,FRIED_SAVEALPHA,124-quality,size); | |
| op->SetBlob(friedBlob,size); | |
| sDPrintF("FRIED-encoded image for '%s' is %d bytes\n",filename,size); | |
| delete[] pic; | |
| } | |
| delete[] data; | |
| data = op->GetBlob(size); | |
| } | |
| #endif | |
| #if sLINK_FRIED | |
| if(data && LoadFRIED(data,size,xs,ys,pic)) | |
| { | |
| bm = new GenBitmap; | |
| bm->Init(xs,ys); | |
| sU32 *s = (sU32 *) pic; | |
| sU64 *d = (sU64 *) bm->Data; | |
| for(sInt i=0;i<xs*ys;i++) | |
| d[i] = GetColor64(s[i]); | |
| delete[] pic; | |
| } | |
| else | |
| sDPrintF("%s\n",data?"Couldn't load":"No data"); | |
| #endif | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| /****************************************************************************/ | |
| static sInt CBTable[3][257]; | |
| static sInt CBLookup(const sInt *table,sInt value) | |
| { | |
| sInt ind = (value >> 7); | |
| return table[ind] + (((table[ind+1] - table[ind]) * (value & 127)) >> 7); | |
| } | |
| GenBitmap * __stdcall Bitmap_ColorBalance(GenBitmap *bm,sF323 shadows,sF323 midtones,sF323 highlights) | |
| { | |
| sInt i,j; | |
| sF32 x; | |
| sF32 vsha,vmid,vhil; | |
| sF32 p; | |
| sF32 min,max,msc; | |
| GenBitmap *in; | |
| static const sF32 sc = 100.0f / 255.0f; | |
| NOTEXTURES1(bm); | |
| if(CheckBitmap(bm,&in)) return 0; | |
| // lookup tables | |
| for(j=0;j<3;j++) | |
| { | |
| vsha = (&shadows.x)[j]; | |
| vmid = (&midtones.x)[j]; | |
| vhil = (&highlights.x)[j]; | |
| p = sFPow(0.5f,vsha * 0.5f + vmid + vhil * 0.5f); | |
| min = -sMin(vsha,0.0f) * sc; | |
| max = 1.0f - sMax(vhil,0.0f) * sc; | |
| msc = 1.0f / (max - min); | |
| for(i=0;i<=256;i++) | |
| { | |
| x = sFPow((sRange(i/256.0f,max,min) - min) * msc,p); | |
| CBTable[j][i] = sRange7fff(x * 32768.0f); | |
| } | |
| } | |
| // now just apply lookup tables | |
| sU16 *d = (sU16 *) bm->Data; | |
| sU16 *s = (sU16 *) in->Data; | |
| for(i=0;i<bm->Size;i++) | |
| { | |
| d[0] = CBLookup(CBTable[2],s[0]); | |
| d[1] = CBLookup(CBTable[1],s[1]); | |
| d[2] = CBLookup(CBTable[0],s[2]); | |
| d[3] = s[3]; | |
| d += 4; | |
| s += 4; | |
| } | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Unwrap(GenBitmap *bm,sInt mode) | |
| { | |
| GenBitmap *in; | |
| BilinearContext ctx; | |
| sU64 *mem; | |
| NOTEXTURES1(bm); | |
| if(CheckBitmap(bm,&in)) return 0; | |
| BilinearSetup(&ctx,in->Data,in->XSize,in->YSize,(mode >> 4) & 3); | |
| sInt wrapMode = mode & 15; | |
| mem = new sU64[in->Size]; | |
| sU16 *d = (sU16 *) mem; | |
| sF32 invX = 1.0f / bm->XSize; | |
| sF32 invY = 1.0f / bm->YSize; | |
| sInt usc = bm->XSize << 16; | |
| sInt vsc = bm->YSize << 16; | |
| for(sInt y=0;y<bm->YSize;y++) | |
| { | |
| sF32 fy = y * invY,fyc = 0.5f - fy; | |
| for(sInt x=0;x<bm->XSize;x++) | |
| { | |
| sF32 fx = x * invX,fxc = fx - 0.5f; | |
| sF32 u,v; | |
| switch(mode & 3) | |
| { | |
| case 0: // polar2normal | |
| sFSinCos(fx * sPI2F,v,u); | |
| u = (1.0f + u * fy) * 0.5f; | |
| v = (1.0f - v * fy) * 0.5f; | |
| break; | |
| case 1: // normal2polar | |
| u = sFATan2(fyc,fxc) / sPI2F; | |
| if(u<0.0f) u += 1.0f; | |
| v = sFSqrt(fxc*fxc + fyc*fyc) * 2.0f; | |
| break; | |
| case 2: // rect2normal | |
| if(sFAbs(fyc) <= sFAbs(fxc)) // 1st or 3rd quadrant | |
| { | |
| v = sFAbs(fxc) * 2.0f; | |
| u = 0.25f - fy / (v * 2.0f); | |
| if(fxc < 0.0f) | |
| u = 0.75f - u; | |
| } | |
| else // 2nd or 4th quadrant | |
| { | |
| v = sFAbs(fyc) * 2.0f; | |
| u = 0.5f - fx / (v * 2.0f); | |
| if(fyc < 0.0f) | |
| u = 1.0f - u; | |
| } | |
| break; | |
| } | |
| BilinearFilter(&ctx,(sU64 *) d,u*usc,v*vsc); | |
| d += 4; | |
| } | |
| } | |
| delete[] bm->Data; | |
| bm->Data = mem; | |
| return bm; | |
| } | |
| GenBitmap * __stdcall Bitmap_Bulge(GenBitmap *bm,sF32 warp) | |
| { | |
| GenBitmap *in; | |
| BilinearContext ctx; | |
| sU64 *mem; | |
| NOTEXTURES1(bm); | |
| if(CheckBitmap(bm,&in)) return 0; | |
| BilinearSetup(&ctx,in->Data,in->XSize,in->YSize,0); | |
| mem = new sU64[bm->Size]; | |
| sU16 *d = (sU16 *) mem; | |
| sF32 invX = 1.0f / bm->XSize; | |
| sF32 invY = 1.0f / bm->YSize; | |
| sInt usc = bm->XSize << 16; | |
| sInt vsc = bm->YSize << 16; | |
| for(sInt y=0;y<bm->YSize;y++) | |
| { | |
| sF32 fy = y * invY,fyc = (0.5f - fy) * 2.0f; | |
| for(sInt x=0;x<bm->XSize;x++) | |
| { | |
| sF32 fx = x * invX,fxc = (fx - 0.5f) * 2.0f; | |
| sF32 u = fxc; | |
| sF32 v = fyc; | |
| sF32 rsq = u*u + v*v; | |
| if(rsq <= 1.0f) | |
| { | |
| sF32 iz = 1.0f / (1.0f + warp * sFSqrt(1.0f - rsq)); | |
| u *= iz; | |
| v *= iz; | |
| } | |
| u = (1.0f + u) * 0.5f; | |
| v = (1.0f - v) * 0.5f; | |
| BilinearFilter(&ctx,(sU64 *) d,u*usc,v*vsc); | |
| d += 4; | |
| } | |
| } | |
| delete[] bm->Data; | |
| bm->Data = mem; | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Bricks(sInt bmxs,sInt bmys,sInt color0,sInt color1,sInt colorf,sF32 ffugex,sF32 ffugey,sInt tx,sInt ty,sInt seed,sInt heads,sInt flags,sF32 side,sF32 colorbalance) | |
| { | |
| GenBitmap *bm; | |
| sU64 *d; | |
| sInt fx,fy; | |
| sInt fugex,fugey; | |
| sInt bx,by; | |
| sU64 c0,c1,cf,cb; | |
| sInt f; | |
| sInt kopf,kopftrigger; | |
| sInt sidestep,sideakku; | |
| sInt multiply; | |
| struct Cell | |
| { | |
| sU64 Color; | |
| sInt Kopf; | |
| } *cells; | |
| bm = NewBitmap(bmxs,bmys); | |
| sSetRndSeed(seed); | |
| d = bm->Data; | |
| c0 = GetColor64(color0); | |
| c1 = GetColor64(color1); | |
| cf = GetColor64(colorf); | |
| fugex = ffugex*0x2000; | |
| fugey = ffugey*0x2000; | |
| sidestep = side*0x4000; | |
| multiply = 1<<((flags>>4)&7); | |
| cells = new Cell[tx*multiply*ty*multiply]; | |
| kopf = 0; | |
| // Fade64(cb,c0,c1,sFPow(sFGetRnd(),colorbalance)*0x10000); | |
| // distribute heads | |
| for(sInt y=0;y<ty;y++) | |
| { | |
| kopftrigger = 0; | |
| for(sInt x=0;x<tx;x++) | |
| { | |
| kopftrigger--; | |
| cells[y*tx*multiply+x].Color = 0; | |
| cells[y*tx*multiply+x].Kopf = kopf; | |
| if(kopf==0) | |
| { | |
| kopf = 1; | |
| } | |
| else | |
| { | |
| if((sInt)sGetRnd(255)>heads || kopftrigger>=0) | |
| { | |
| kopf = 0; | |
| } | |
| else | |
| if(flags&4) kopftrigger=2; | |
| } | |
| // if(kopf) | |
| // Fade64(cb,c0,c1,sFPow(sFGetRnd(),colorbalance)*0x10000); | |
| } | |
| if(!cells[y*tx*multiply].Kopf && !cells[y*tx*multiply+tx-1].Kopf) | |
| cells[y*tx*multiply].Kopf = 1; | |
| if(flags & 4) | |
| { | |
| if(cells[y*tx*multiply].Kopf && cells[y*tx*multiply+1].Kopf && cells[y*tx*multiply+2].Kopf) | |
| cells[y*tx*multiply+1].Kopf = 0; | |
| if(cells[y*tx*multiply+tx-1].Kopf && cells[y*tx*multiply].Kopf && cells[y*tx*multiply+1].Kopf) | |
| cells[y*tx*multiply].Kopf = 0; | |
| if(cells[y*tx*multiply+tx-2].Kopf && cells[y*tx*multiply+tx-1].Kopf && cells[y*tx*multiply].Kopf) | |
| cells[y*tx*multiply+tx-1].Kopf = 0; | |
| } | |
| } | |
| // multiply head pattern | |
| for(sInt yy=0;yy<multiply;yy++) | |
| { | |
| for(sInt y=0;y<ty;y++) | |
| { | |
| for(sInt xx=0;xx<multiply;xx++) | |
| { | |
| for(sInt x=0;x<tx;x++) | |
| { | |
| cells[(yy*ty+y)*(multiply*tx)+xx*tx+x] = cells[(y)*(multiply*tx)+x]; | |
| } | |
| } | |
| } | |
| } | |
| // distribute colors | |
| tx *= multiply; | |
| ty *= multiply; | |
| Fade64(cb,c0,c1,sFPow(sFGetRnd(),colorbalance)*0x10000); | |
| for(sInt y=0;y<ty;y++) | |
| { | |
| for(sInt x=0;x<tx;x++) | |
| { | |
| if(cells[y*tx+x].Kopf) | |
| Fade64(cb,c0,c1,sFPow(sFGetRnd(),colorbalance)*0x10000); | |
| cells[y*tx+x].Color = cb; | |
| } | |
| if(!cells[y*tx].Kopf) | |
| cells[y*tx].Color = cells[y*tx+tx-1].Color; | |
| } | |
| // do the painting | |
| sInt bmx = 0x4000/bm->XSize*tx; | |
| sInt bmy = 0x4000/bm->YSize*ty; | |
| sideakku = 0; | |
| for(sInt y=0;y<bm->YSize;y++) | |
| { | |
| fy = 0x4000/bm->YSize*y*ty; | |
| by = fy>>14; | |
| sVERIFY(by<ty); | |
| fy = fy&0x3fff; | |
| sideakku = (by*sidestep)&0x7fff; | |
| for(sInt x=0;x<bm->XSize;x++) | |
| { | |
| fx = 0x4000/bm->XSize*x*tx; | |
| fx += sideakku; | |
| bx = fx>>14; | |
| if(bx>=tx) bx-=tx; | |
| fx = fx&0x3fff; | |
| if(flags&8) | |
| { | |
| f = 0x4000; | |
| if(cells[by*tx+(bx+0)%tx].Kopf) | |
| if( fx<fugex) f = 0x4000*sMax(0,(( fx)-(fugex-bmx)))/bmx; | |
| if(cells[by*tx+(bx+1)%tx].Kopf) | |
| if(0x4000-fx<fugex) f = 0x4000*sMax(0,((0x4000-fx)-(fugex-bmx)))/bmx; | |
| if( fy<fugey) f = sMin(f,0x4000*sMax(0,(( fy)-(fugey-bmy)))/bmy); | |
| if(0x4000-fy<fugey) f = sMin(f,0x4000*sMax(0,((0x4000-fy)-(fugey-bmy)))/bmy); | |
| } | |
| else | |
| { | |
| f = 0x4000; | |
| if(cells[by*tx+(bx+0)%tx].Kopf) | |
| if( fx<fugex) f = 0x4000* fx /fugex; | |
| if(cells[by*tx+(bx+1)%tx].Kopf) | |
| if(0x4000-fx<fugex) f = 0x4000*(0x4000-fx)/fugex; | |
| if( fy<fugey) f = sMin(f,0x4000* fy /fugey); | |
| if(0x4000-fy<fugey) f = sMin(f,0x4000*(0x4000-fy)/fugey); | |
| } | |
| Fade64(*d,cf,cells[by*tx+bx%tx].Color,f*4); | |
| d++; | |
| } | |
| } | |
| delete[] cells; | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| #if sLINK_ENGINE | |
| /****************************************************************************/ | |
| void _stdcall Exec_Bitmap_Render(sInt xs,sInt ys) | |
| { | |
| } | |
| void _stdcall Exec_Bitmap_RenderAuto(sInt xs,sInt ys,sInt flags) | |
| { | |
| } | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_Render(KOp *op,class GenIPP *ipp,sInt xs,sInt ys) | |
| { | |
| NOTEXTURES0(); | |
| sViewport view; | |
| sTexInfo tif; | |
| GenBitmap *bm; | |
| bm = NewBitmap(xs,ys); | |
| tif.InitRT(bm->XSize,bm->YSize); | |
| sInt tex = sSystem->AddTexture(tif); | |
| view.InitTexMS(tex); | |
| sSystem->SetViewport(view); | |
| sSystem->Clear(sVCF_ALL,0xffff8080); | |
| // taken vom Exec_IPP_RenderTarget | |
| { | |
| // just tweak the master viewport | |
| sViewport saved,newvp; | |
| GenOverlayManager->GetMasterViewport(saved); | |
| newvp.InitTexMS(tex); | |
| GenOverlayManager->SetMasterViewport(newvp); | |
| // render | |
| KEnvironment *kenv=new KEnvironment; | |
| kenv->InitView(); | |
| kenv->InitFrame(0,0); | |
| op->ExecInputs(kenv); | |
| kenv->ExitFrame(); | |
| delete kenv; | |
| // restore | |
| GenOverlayManager->SetMasterViewport(saved); | |
| } | |
| sSystem->FinishMSBlit(); | |
| sSystem->ReadTexture(tex,(sU16 *)bm->Data); | |
| sSystem->RemTexture(tex); | |
| sRelease(ipp); | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| GenBitmap * __stdcall Bitmap_RenderAuto(KOp *op,class GenMinMesh *mesh,sInt xs,sInt ys,sInt flags) | |
| { | |
| NOTEXTURES0(); | |
| sViewport view; | |
| sTexInfo tif; | |
| GenBitmap *bm; | |
| sMatrix mat; | |
| EngLight light; | |
| sMaterialEnv env; | |
| sAABox box; | |
| sInt fieldcount; | |
| sInt fieldmax; | |
| sViewport saved,newvp; | |
| sVector boxmin,boxmax; | |
| bm = NewBitmap(xs,ys); | |
| sSetMem8(bm->Data,0xffff0000ffff0000ULL,bm->Size); | |
| tif.InitRT(bm->XSize,bm->YSize); | |
| sInt tex = sSystem->AddTexture(tif); | |
| mesh->CalcBBox(box); | |
| fieldcount = 0; | |
| fieldmax = 0; | |
| for(sInt i=0;i<6;i++) | |
| if(flags & (1<<i)) | |
| fieldmax++; | |
| GenOverlayManager->GetMasterViewport(saved); | |
| newvp.InitTexMS(tex); | |
| GenOverlayManager->SetMasterViewport(newvp); | |
| RenderTargetManager->SetMasterViewport(newvp); | |
| for(sInt i=0;i<6;i++) | |
| { | |
| if(flags & (1<<i)) | |
| { | |
| env.Init(); | |
| light.Type = sLT_POINT; | |
| light.Position.Init(0,0,-1024); | |
| light.Direction.Init(0,0,1); | |
| light.Flags = 0; | |
| light.Color = 0xffffffff; | |
| light.Amplify = 1.0f; | |
| light.Range = 2048; | |
| light.Event = 0; | |
| light.Id = 0; | |
| mat.InitClassify(i); | |
| mat.Trans3(); | |
| boxmin.Rotate34(mat,box.Min); | |
| boxmax.Rotate34(mat,box.Max); | |
| env.CameraSpace.l.x = (boxmin.x + boxmax.x)/2; | |
| env.CameraSpace.l.y = (boxmin.y + boxmax.y)/2; | |
| env.CameraSpace.l.z = -256; | |
| env.ZoomX = 2.0f/sFAbs(boxmax.x-boxmin.x); | |
| env.ZoomY = 2.0f/sFAbs(boxmax.y-boxmin.y); | |
| env.Orthogonal = 1; | |
| KEnvironment *kenv = new KEnvironment; | |
| kenv->InitView(); | |
| kenv->InitFrame(0,0); | |
| view.InitTexMS(tex); | |
| view.Window.x0 = bm->XSize * fieldcount / fieldmax; | |
| view.Window.x1 = bm->XSize * (fieldcount+1) / fieldmax; | |
| sSystem->SetViewport(view); | |
| sSystem->Clear(sVCF_ALL,0x00000000); | |
| // sSystem->SetViewProject(env); | |
| mesh->Prepare(); | |
| Engine->StartFrame(); | |
| Engine->SetViewProject(env); | |
| Engine->AddPaintJob(mesh->PreparedMesh,mat,0.0f); | |
| Engine->AddLightJob(light); | |
| Engine->ProcessPortals(kenv,0); | |
| Engine->Paint(kenv); | |
| kenv->ExitFrame(); | |
| delete kenv; | |
| fieldcount++; | |
| } | |
| } | |
| GenOverlayManager->SetMasterViewport(saved); | |
| RenderTargetManager->SetMasterViewport(saved); | |
| sSystem->FinishMSBlit(); | |
| sSystem->ReadTexture(tex,(sU16 *)bm->Data); | |
| sSystem->RemTexture(tex); | |
| sRelease(mesh); | |
| return bm; | |
| } | |
| #endif // sLINK_ENGINE | |
| GenBitmap * __stdcall Bitmap_Export(GenBitmap *bm,sChar *filename,sInt flags) | |
| { | |
| NOTEXTURES1(bm); | |
| if(CheckBitmap(bm)) return 0; | |
| return bm; | |
| } | |
| GenBitmap * __stdcall Bitmap_Paste(GenBitmap *bm,GenBitmap *bs,sF322 pre,sF322 pos,sF322 size,sF32 angle,sInt mode) | |
| { | |
| NOTEXTURES2(bm,bs); | |
| if(CheckBitmap(bm)) return 0; | |
| // sign stuff | |
| if(pre.x < 0.0f) | |
| pre.x = -pre.x, size.x = -size.x; | |
| if(pre.y < 0.0f) | |
| pre.y = -pre.y, size.y = -size.y; | |
| pre.x *= bs->XSize; | |
| pre.y *= bs->YSize; | |
| // calc transformed quad points | |
| sF32 s,c; | |
| sFSinCos(angle*sPI2F,s,c); | |
| sF32 ux = size.x * c; | |
| sF32 uy = size.x * -s; | |
| sF32 vx = size.y * s; | |
| sF32 vy = size.y * c; | |
| sF32 orgx = pos.x - 0.5f * (ux + vx); | |
| sF32 orgy = pos.y - 0.5f * (uy + vy); | |
| // calculate bounding rect | |
| sInt XRes = bm->XSize, YRes = bm->YSize; | |
| sInt minX = sMax<sInt>(0,((orgx + sMin(ux,0.0f) + sMin(vx,0.0f)) * XRes) - 1); | |
| sInt minY = sMax<sInt>(0,((orgy + sMin(uy,0.0f) + sMin(vy,0.0f)) * YRes) - 1); | |
| sInt maxX = sMin<sInt>(XRes-1,((orgx + sMax(ux,0.0f) + sMax(vx,0.0f)) * XRes) + 1); | |
| sInt maxY = sMin<sInt>(YRes-1,((orgy + sMax(uy,0.0f) + sMax(vy,0.0f)) * YRes) + 1); | |
| // solve for u0,v0 and deltas (Cramer's rule) | |
| sF32 detM = ux*vy - uy*vx; | |
| if(fabs(detM) * XRes * YRes < 0.25f) // smaller than a pixel? skip it. | |
| return bm; | |
| sF32 invM = (1 << 16) / detM; | |
| sF32 rmx = (minX + 0.5f) / XRes - orgx; | |
| sF32 rmy = (minY + 0.5f) / YRes - orgy; | |
| sInt u0 = (rmx*vy - rmy*vx) * invM * pre.x; | |
| sInt v0 = (ux*rmy - uy*rmx) * invM * pre.y; | |
| sInt dudx = vy * invM * pre.x / XRes; | |
| sInt dvdx = -uy * invM * pre.y / XRes; | |
| sInt dudy = -vx * invM * pre.x / YRes; | |
| sInt dvdy = ux * invM * pre.y / YRes; | |
| sU32 maxU = pre.x * 65536; | |
| sU32 maxV = pre.y * 65536; | |
| sU32 mskUV = ~0u; | |
| sInt uvOff = 0; | |
| if(mode & 128) // nearest neighbor | |
| { | |
| mskUV = ~0xffff; | |
| uvOff = 0x8000; | |
| } | |
| mode &= 127; | |
| // render | |
| BilinearContext ctx; | |
| BilinearSetup(&ctx,bs->Data,bs->XSize,bs->YSize,0); | |
| for(sInt y=minY;y<=maxY;y++) | |
| { | |
| sU64 *out = &bm->Data[y*XRes]; | |
| sInt u = u0; | |
| sInt v = v0; | |
| for(sInt x=minX;x<=maxX;x++) | |
| { | |
| if((unsigned) u < maxU && (unsigned) v < maxV) | |
| { | |
| sU64 pix; | |
| BilinearFilter(&ctx,&pix,(u & mskUV) + uvOff,(v & mskUV) + uvOff); | |
| if(mode) | |
| Fade64(out[x],out[x],pix,(pix >> 48) << 1); | |
| else | |
| out[x] = pix; | |
| } | |
| u += dudx; | |
| v += dvdx; | |
| } | |
| u0 += dudy; | |
| v0 += dvdy; | |
| } | |
| return bm; | |
| } | |
| /****************************************************************************/ | |
| /*** ***/ | |
| /*** Generator ***/ | |
| /*** ***/ | |
| /****************************************************************************/ | |
| GenBitmap::GenBitmap() | |
| { | |
| Data = 0; | |
| XSize = 0; | |
| YSize = 0; | |
| Size = 0; | |
| Texture = sINVALID; | |
| ClassId = KC_BITMAP; | |
| Format = GenBitmapDefaultFormat; | |
| TexMipCount = 0; | |
| TexMipTresh = 0; | |
| } | |
| GenBitmap::~GenBitmap() | |
| { | |
| if(Data) delete[] Data; | |
| if(Texture!=sINVALID) sSystem->RemTexture(Texture); | |
| } | |
| void GenBitmap::Copy(KObject *o) | |
| { | |
| GenBitmap *ob; | |
| sVERIFY(o->ClassId==KC_BITMAP); | |
| ob = (GenBitmap *) o; | |
| sVERIFY(ob->Data); | |
| Texture = sINVALID; | |
| Init(ob->XSize,ob->YSize); | |
| Format = ob->Format; | |
| TexMipCount = ob->TexMipCount; | |
| TexMipTresh = ob->TexMipTresh; | |
| sCopyMem4((sU32 *)Data,(sU32 *)ob->Data,Size*2); | |
| } | |
| KObject *GenBitmap::Copy() | |
| { | |
| GenBitmap *r; | |
| r = new GenBitmap; | |
| r->Copy(this); | |
| return r; | |
| } | |
| void GenBitmap::Init(sInt x,sInt y) | |
| { | |
| XSize = x; | |
| YSize = y; | |
| Size = x*y; | |
| Data = new sU64[Size]; | |
| Stripped = sFALSE; | |
| } | |
| void GenBitmap::MakeTexture(sInt format) | |
| { | |
| if(Texture!=sINVALID) | |
| sSystem->RemTexture(Texture); | |
| if(format!=0) | |
| Format = format; | |
| Texture = sSystem->AddTexture(XSize,YSize,Format,(sU16 *)Data,TexMipCount,TexMipTresh); | |
| } | |
| sBool GenBitmap::Strip() | |
| { | |
| if(Texture != sINVALID) | |
| { | |
| delete[] Data; | |
| Data = 0; | |
| Size = 0; | |
| Stripped = sTRUE; | |
| return sTRUE; | |
| } | |
| else | |
| return sFALSE; | |
| } | |
| sBool GenBitmap::IsStripped() | |
| { | |
| return Stripped; | |
| } | |
| /****************************************************************************/ | |
| /****************************************************************************/ |