Code: Select all
' Multiput by D.J.Peters (Joshy)
' MultiPut [destination],[xmidpos],[ymidpos],source,[xScale],[yScale],[Trans]
type FP16 ' fixed point 16:16
union
type
as ushort l
as short h
end type
as integer v
end union
end type
#macro DrawSpawn(_type_)
var t=cptr(_type_ ptr,pTarget)+yStart*TargetPitch+xStart
xStart=0
If Transparent=false Then
While xStart<xEnd
var s=cptr(_type_ ptr,pSource)+V.h*SourcePitch+U.h
*t=*s
U.v+=US.v : V.v+=VS.v : If v.v<0 Then v.v=0
xStart+=1:t+=1
Wend
Else
While xStart<xEnd
var s=cptr(_type_ ptr,pSource)+V.h*SourcePitch+U.h
If *s Then *t=*s
U.v+=US.v : V.v+=VS.v : If v.v<0 Then v.v=0
xStart+=1:t+=1
Wend
End If
#endmacro
#define _ADD_ 0 ' increment a value
#define _CMP_ 1 ' compare a values
#define _SET_ 2 ' set a value
#define _XScreen_ 0
#define _YScreen_ 1
#define _UTexture_ 2
#define _VTexture_ 3
#define _LeftIndex_ 0
#define _RightIndex_ 1
#define _CurrentIndex_ 0
#define _NextIndex_ 1
#define _EdgeXStart_ 0
#define _EdgeUStart_ 1
#define _EdgeVStart_ 2
#define _EdgeXStep_ 3
#define _EdgeUStep_ 4
#define _EdgeVStep_ 5
'#define UseRad 'if not then Rotate are in degrees
Sub MultiPut(Byval pTarget As Any Ptr= 0, _
Byval xMidPos As Integer= 0, _
Byval yMidPos As Integer= 0, _
Byval pSource As Any Ptr , _
Byval xScale As Single = 1, _
Byval yScale As Single = 1, _
Byval Rotate As Single = 0, _
Byval Transparent As boolean = false)
Dim As Integer SourceWidth=any,SourceHeight=any,SourceBytes=any,SourcePitch=any
Dim as Integer TargetWidth=any,TargetHeight=any,TargetBytes=any,TargetPitch=any
Dim As Integer i=any,yStart=any,yEnd=any,xStart=any,xEnd=any
Dim As Integer CNS(1,1)=any 'Counters
Dim As Integer ACS(1,2)=any '_ADD_ compare and _SET_
Dim As Single fPoints(3,3)=any,fEdges(2,6)=any,fLength=any,fUSlope=any,fVSlope=any
Dim As FP16 U=any,V=any,US=any,VS=any
Dim As boolean MustRotate = iif(Rotate<>0,true,false)
If (screenptr=0) Or (pSource=0) Then Exit Sub
If xScale < 0.001 Then xScale=0.001
If yScale < 0.001 Then yScale=0.001
If pTarget=0 Then
ScreenInfo _
TargetWidth , _
TargetHeight,, _
TargetBytes ,_
TargetPitch
pTarget=ScreenPtr
Else
TargetBytes = cptr(uinteger Ptr,pTarget)[1]
TargetWidth = cptr(uinteger Ptr,pTarget)[2]
TargetHeight = cptr(uinteger Ptr,pTarget)[3]
TargetPitch = cptr(uinteger Ptr,pTarget)[4]
pTarget += 32
End If
If (TargetWidth<4) Or (TargetHeight<4) Then Exit Sub
SourceBytes = cptr(uinteger Ptr,pSource)[1]
If (TargetBytes<>SourceBytes) Then Exit Sub
SourceWidth = cptr(uinteger Ptr,pSource)[2]
SourceHeight = cptr(uinteger Ptr,pSource)[3]
If (SourceWidth<2) Or (SourceHeight<2) Then Exit Sub
SourcePitch = cptr(uinteger Ptr,pSource)[4]
pSource += 32
Select Case as const TargetBytes
case 1 ' TargetPitch shr=0 : SourcePitch shr=0
case 2 : TargetPitch shr=1 : SourcePitch shr=1
case 4 : TargetPitch shr=2 : SourcePitch shr=2
case else : exit sub
end select
fPoints(0,_XScreen_)=-SourceWidth/2 * xScale
fPoints(1,_XScreen_)= SourceWidth/2 * xScale
fPoints(2,_XScreen_)= fPoints(1,_XScreen_)
fPoints(3,_XScreen_)= fPoints(0,_XScreen_)
fPoints(0,_YScreen_)=-SourceHeight/2 * yScale
fPoints(1,_YScreen_)= fPoints(0,_YScreen_)
fPoints(2,_YScreen_)= SourceHeight/2 * yScale
fPoints(3,_YScreen_)= fPoints(2,_YScreen_)
fPoints(1,_UTexture_)= SourceWidth
fPoints(2,_UTexture_)= fPoints(1,_UTexture_)
fPoints(2,_VTexture_)= SourceHeight
fPoints(3,_VTexture_)= fPoints(2,_VTexture_)
If MustRotate=true Then
#ifndef UseRad
Rotate*=0.017453292 'degre 2 rad
#endif
'While Rotate< 0 :rotate+=6.2831853:Wend
'While Rotate>=6.2831853:rotate-=6.2831853:Wend
For i=0 To 3
var x =fPoints(i,_XScreen_)*Cos(Rotate) - fPoints(i,_YScreen_)*Sin(Rotate)
var y =fPoints(i,_XScreen_)*Sin(Rotate) + fPoints(i,_YScreen_)*Cos(Rotate)
fPoints(i,_XScreen_)=x:fPoints(i,_YScreen_)=y
Next
End If
yStart=30^2:yEnd=-yStart:xStart=yStart:xEnd=yEnd
' get min max
For i=0 To 3
fPoints(i,_XScreen_)=Int(fPoints(i,_XScreen_)+xMidPos)
fPoints(i,_YScreen_)=Int(fPoints(i,_YScreen_)+yMidPos)
If fPoints(i,_YScreen_)<yStart Then yStart=fPoints(i,_YScreen_):CNS(_LeftIndex_,_CurrentIndex_)=i
If fPoints(i,_YScreen_)>yEnd Then yEnd =fPoints(i,_YScreen_)
If fPoints(i,_XScreen_)<xStart Then xStart=fPoints(i,_XScreen_)
If fPoints(i,_XScreen_)>xEnd Then xEnd =fPoints(i,_XScreen_)
Next
If yStart =yEnd Then Exit Sub
If yStart>=TargetHeight Then Exit Sub
If yEnd <0 Then Exit Sub
If xStart = xEnd Then Exit Sub
If xStart>=TargetWidth Then Exit Sub
If xEnd <0 Then Exit Sub
ACS(_LeftIndex_ ,_ADD_)=-1:ACS(_LeftIndex_ ,_CMP_)=-1:ACS(_LeftIndex_ ,_SET_)=3
ACS(_RightIndex_,_ADD_)= 1:ACS(_RightIndex_,_CMP_)= 4:ACS(_RightIndex_,_SET_)=0
' share the same highest point
CNS(_RightIndex_,_CurrentIndex_)=CNS(_LeftIndex_,_CurrentIndex_)
' loop from Top to Bottom
While yStart<yEnd
'Scan Left and Right edges together
For i=_LeftIndex_ To _RightIndex_
' bad to read but fast and short ;-)
If yStart=fPoints(CNS(i,_CurrentIndex_),_YScreen_) Then
CNS(i,_NextIndex_)=CNS(i,_CurrentIndex_)+ACS(i,_ADD_)
If CNS(i,_NextIndex_)=ACS(i,_CMP_) Then CNS(i,_NextIndex_)=ACS(i,_SET_)
While fPoints(CNS(i,_CurrentIndex_),_YScreen_) = fPoints(CNS(i,_NextIndex_),_YScreen_)
CNS(i,_CurrentIndex_)=CNS(i,_NextIndex_)
CNS(i,_NextIndex_ )=CNS(i,_CurrentIndex_)+ACS(i,_ADD_)
If CNS(i,_NextIndex_)=ACS(i,_CMP_) Then CNS(i,_NextIndex_)=ACS(i,_SET_)
Wend
fEdges(i,_EdgeXStart_) = fPoints(CNS(i,_CurrentIndex_),_XScreen_)
fEdges(i,_EdgeUStart_) = fPoints(CNS(i,_CurrentIndex_),_UTexture_)
fEdges(i,_EdgeVStart_) = fPoints(CNS(i,_CurrentIndex_),_VTexture_)
fLength = fPoints(CNS(i,_NextIndex_),_YScreen_) - fPoints(CNS(i,_CurrentIndex_),_YScreen_)
If fLength <> 0.0 Then
fLength=1/fLength
fEdges(i,_EdgeXStep_) = fPoints(CNS(i,_NextIndex_),_XScreen_ )-fEdges(i,_EdgeXStart_):fEdges(i,_EdgeXStep_)*=fLength
fEdges(i,_EdgeUStep_) = fPoints(CNS(i,_NextIndex_),_UTexture_)-fEdges(i,_EdgeUStart_):fEdges(i,_EdgeUStep_)*=fLength
fEdges(i,_EdgeVStep_) = fPoints(CNS(i,_NextIndex_),_VTexture_)-fEdges(i,_EdgeVStart_):fEdges(i,_EdgeVStep_)*=fLength
End If
CNS(i,_CurrentIndex_)=CNS(i,_NextIndex_)
End If
Next
If (yStart<0) Then Goto SkipScanLine
xStart=fEdges(_LeftIndex_ ,_EdgeXStart_) :If xStart>=TargetWidth Then Goto SkipScanLine
xEnd =fEdges(_RightIndex_,_EdgeXStart_):If xEnd < 0 Then Goto SkipScanLine
If (xStart=xEnd) Then Goto SkipScanLine
if xEnd <xStart Then goto SkipScanLine
fLength=1/(xEnd-xStart)
fUSlope=fEdges(_RightIndex_,_EdgeUStart_)-fEdges(_LeftIndex_,_EdgeUStart_):fUSlope*=fLength
fVSlope=fEdges(_RightIndex_,_EdgeVStart_)-fEdges(_LeftIndex_,_EdgeVStart_):fVSlope*=fLength
If xstart<0 Then
fLength=Abs(xStart)
U.v=(fEdges(_LeftIndex_,_EdgeUStart_)+fUSlope*fLength)*65536
V.v=(fEdges(_LeftIndex_,_EdgeVStart_)+fVSlope*fLength)*65536
xStart = 0
Else
U.v=fEdges(_LeftIndex_,_EdgeUStart_)*65536
V.v=fEdges(_LeftIndex_,_EdgeVStart_)*65536
End If
If u.v<0 Then u.v=0
If v.v<0 Then v.v=0
US.v=fUSlope*65536
VS.v=fVSlope*65536
If xEnd>=TargetWidth Then xEnd=TargetWidth-1
xEnd-=xStart
Select Case as const TargetBytes
Case 1
DrawSpawn(ubyte)
Case 2
DrawSpawn(ushort)
Case 4
DrawSpawn(ulong)
End Select
SkipScanLine:
yStart+=1 : If yStart=TargetHeight Then exit while
fEdges(_LeftIndex_ ,_EdgeXStart_)+=fEdges(_LeftIndex_ ,_EdgeXStep_)
fEdges(_LeftIndex_ ,_EdgeUStart_)+=fEdges(_LeftIndex_ ,_EdgeUStep_)
fEdges(_LeftIndex_ ,_EdgeVStart_)+=fEdges(_LeftIndex_ ,_EdgeVStep_)
fEdges(_RightIndex_,_EdgeXStart_)+=fEdges(_RightIndex_,_EdgeXStep_)
fEdges(_RightIndex_,_EdgeUStart_)+=fEdges(_RightIndex_,_EdgeUStep_)
fEdges(_RightIndex_,_EdgeVStart_)+=fEdges(_RightIndex_,_EdgeVStep_)
Wend
End Sub
screenres 1024,480,32
dim as integer w,h
screeninfo w,h
var img=ImageCreate(128,128,rgb(255,255,255))
line img,(0,0)-step(127,127),RGB(255,255,255),BF
for i as integer = 0 to 127 step 32
line img,(i,0)-step(0,127),rgb(128,128,128)
line img,(i+1,0)-step(0,127),rgb(128,128,128)
line img,(0,i)-step(127,0),rgb(128,128,128)
line img,(0,i+1)-step(127,0),rgb(128,128,128)
next
for i as integer = 0 to 3
line img,(i,i)-step(127-i*2,127-i*2),RGB(0,0,255),B
next
draw string img,(24,9),"MultiPut()",RGB(0,0,0)
dim as single rot
while inkey()=""
screenlock : line (0,0)-step(w-1,h-1),0,BF
dim as single x
for i as integer = 1 to 7
dim as single scale = i*.25
x+=scale*128
multiPut ,x,240,img,scale,scale,rot
next
put (2,2),img,PSET
screenunlock
rot+=.5
sleep 10
wend