[Plugin] S-ART [place any picture on the map like an object!]
#41

I just made an interesting billboard, from photoshop to sa-mp. I like the plugin but I'll wait to actually implement it...
Reply
#42

Quote:
Originally Posted by JustBored
Посмотреть сообщение
No, its not maybe you forget to upload it. I need it because i think that i found a way of calling CreateDynamicObject without using the GDK (using amx_Callback)
here
https://sampforum.blast.hk/showthread.php?tid=521365

Quote:

Q: How to use it?
A:
1. Download this archive with ....

Reply
#43

Another thing dude you should add some functions to get the objectids then you could easily add rotation to your include.
Reply
#44

Quote:
Originally Posted by Pottus
Посмотреть сообщение
Another thing dude you should add some functions to get the objectids then you could easily add rotation to your include.
rotation? easily??

rotation processing is the most difficult part in my plugin/tool.

Код:
double up[3] = {sin(ra[1])*cos(ra[2]) + sin(ra[0])*sin(ra[2])*cos(ra[1]), sin(ra[2])*sin(ra[1]) - sin(ra[0])*cos(ra[1])*cos(ra[2]), -cos(ra[0])*cos(ra[1])};
	double right[3] = {-sin(ra[2])*cos(ra[0]), cos(ra[0])*cos(ra[2]), -sin(ra[0])};
	double forward[3] = {cos(ra[1])*cos(ra[2]) - sin(ra[0])*sin(ra[2])*sin(ra[1]), sin(ra[2])*cos(ra[1]) + sin(ra[0])*sin(ra[1])*cos(ra[2]), cos(ra[0])*sin(ra[1])};
the image isn't solid, so I have to calculate all objects position for the ideal alignment. when you change the rotation angles, you must recalculate all positions again

SA math engine uses non-standart Z-X-Y rotation (ffs, wasted few hours until understood that), so my python tool process rotations in a wrong way. I've fixed that in plugin. But you can see what happens with bad alignment, just set angles like 15 - 45 - 75 using that tool
Reply
#45

Here is how you can do it.

1.) Find the group center of all objects
2.) Rotate each object with the following function

pawn Код:
// Credits: Stylock
stock AttachPoint(Float:offx, Float:offy, Float:offz, Float:offrx, Float:offry, Float:offrz, Float:px, Float:py, Float:pz, Float:prx, Float:pry, Float:prz, &Float:RetX, &Float:RetY, &Float:RetZ, &Float:RetRX, &Float:RetRY, &Float:RetRZ, sync_rotation = 1)
{
    new
        Float:g_sin[3],
        Float:g_cos[3],
        Float:off_x,
        Float:off_y,
        Float:off_z;

    EDIT_FloatEulerFix(prx, pry, prz);

    off_x = offx - px; // static offset
    off_y = offy - py; // static offset
    off_z = offz - pz; // static offset

    // Calculate the new position
    EDIT_FloatConvertValue(prx, pry, prz, g_sin, g_cos);
    RetX = px + off_x * g_cos[1] * g_cos[2] - off_x * g_sin[0] * g_sin[1] * g_sin[2] - off_y * g_cos[0] * g_sin[2] + off_z * g_sin[1] * g_cos[2] + off_z * g_sin[0] * g_cos[1] * g_sin[2];
    RetY = py + off_x * g_cos[1] * g_sin[2] + off_x * g_sin[0] * g_sin[1] * g_cos[2] + off_y * g_cos[0] * g_cos[2] + off_z * g_sin[1] * g_sin[2] - off_z * g_sin[0] * g_cos[1] * g_cos[2];
    RetZ = pz - off_x * g_cos[0] * g_sin[1] + off_y * g_sin[0] + off_z * g_cos[0] * g_cos[1];

    if (sync_rotation)
    {
        // Calculate the new rotation
        EDIT_FloatConvertValue(asin(g_cos[0] * g_cos[1]), atan2(g_sin[0], g_cos[0] * g_sin[1]) + offrz, atan2(g_cos[1] * g_cos[2] * g_sin[0] - g_sin[1] * g_sin[2], g_cos[2] * g_sin[1] - g_cos[1] * g_sin[0] * -g_sin[2]), g_sin, g_cos);
        EDIT_FloatConvertValue(asin(g_cos[0] * g_sin[1]), atan2(g_cos[0] * g_cos[1], g_sin[0]), atan2(g_cos[2] * g_sin[0] * g_sin[1] - g_cos[1] * g_sin[2], g_cos[1] * g_cos[2] + g_sin[0] * g_sin[1] * g_sin[2]), g_sin, g_cos);
        EDIT_FloatConvertValue(atan2(g_sin[0], g_cos[0] * g_cos[1]) + offrx, asin(g_cos[0] * g_sin[1]), atan2(g_cos[2] * g_sin[0] * g_sin[1] + g_cos[1] * g_sin[2], g_cos[1] * g_cos[2] - g_sin[0] * g_sin[1] * g_sin[2]), g_sin, g_cos);

        RetRX = asin(g_cos[1] * g_sin[0]);
        RetRY = atan2(g_sin[1], g_cos[0] * g_cos[1]) + offry;
        RetRZ = atan2(g_cos[0] * g_sin[2] - g_cos[2] * g_sin[0] * g_sin[1], g_cos[0] * g_cos[2] + g_sin[0] * g_sin[1] * g_sin[2]);
    }
}





stock EDIT_FloatConvertValue(Float:rot_x, Float:rot_y, Float:rot_z, Float:sin[3], Float:cos[3])
{
    sin[0] = floatsin(rot_x, degrees);
    sin[1] = floatsin(rot_y, degrees);
    sin[2] = floatsin(rot_z, degrees);
    cos[0] = floatcos(rot_x, degrees);
    cos[1] = floatcos(rot_y, degrees);
    cos[2] = floatcos(rot_z, degrees);
    return 1;
}

/*
 * Fixes a bug that causes objects to not rotate
 * correctly when rotating on the Z axis only.
 */

stock EDIT_FloatEulerFix(&Float:rot_x, &Float:rot_y, &Float:rot_z)
{
    EDIT_FloatGetRemainder(rot_x, rot_y, rot_z);
    if((!floatcmp(rot_x, 0.0) || !floatcmp(rot_x, 360.0))
    && (!floatcmp(rot_y, 0.0) || !floatcmp(rot_y, 360.0)))
    {
        rot_y = 0.00000002;
    }
    return 1;
}

stock EDIT_FloatGetRemainder(&Float:rot_x, &Float:rot_y, &Float:rot_z)
{
    EDIT_FloatRemainder(rot_x, 360.0);
    EDIT_FloatRemainder(rot_y, 360.0);
    EDIT_FloatRemainder(rot_z, 360.0);
    return 1;
}

stock EDIT_FloatRemainder(&Float:remainder, Float:value)
{
    if(remainder >= value)
    {
        while(remainder >= value)
        {
            remainder = remainder - value;
        }
    }
    else if(remainder < 0.0)
    {
        while(remainder < 0.0)
        {
            remainder = remainder + value;
        }
    }
    return 1;
}
You should be able to convert that code to work in c++ for your plugin fairly easily.
Reply
#46

soo.. you want something with dynamic objects and manual rotation?

but as you said, dynamic object creation worked not good, I don't think it worth to continue developing
Reply
#47

There is some issue when I tried that results in the image not being rendered correctly try it yourself and you will see.
Reply
#48

I will try to convert that code to C++ and see if it works.
Reply
#49

Quote:
Originally Posted by JustBored
Посмотреть сообщение
I will try to convert that code to C++ and see if it works.
this whole thread is just release of that converted to C++ and improved code -_-
Reply
#50

Idk if this code works (actually it should) because i wasnt able to test it, it removes the "arts" limit by using a vector and a map; try it out:

pawn Код:
struct a_vectors
{
    std::map<int, int> arts_array;
};
std::vector<a_vectors*> vectors;

cell AMX_NATIVE_CALL DestroyArt(AMX* amx, cell* params)
{
    for (auto& i : vectors.at(params[1])->arts_array)
    {
        if (i.second != -1)
        {
            g_Invoke->callNative(&PAWN::DestroyObject, i.second);
        }
    }
    vectors.erase((vectors.begin() + params[1])-1);
    return 1;
}

//CreateArt(path, sX, sY, sZ, aX, aY, aZ, dist, type)
cell AMX_NATIVE_CALL CreateArt(AMX* amx, cell* params)
{
    int cre_f = 0;

    PNG_Struct picture;
    char *text = new char;
    amx_StrParam(amx, params[1],text);

    int open_result = picture.Init(text);
    free(text);

    if(open_result == 1)
    {
        logprintf("FAILED to create art: can't load PNG picture");
        return -1;
    }
    if(open_result == -1)
    {
        logprintf("FAILED to create art: PNG isn't 24-bit type");
        return -1;
    }
    float pos[3] = {amx_ctof(params[2]), amx_ctof(params[3]), amx_ctof(params[4])};
    float ang[3] = {amx_ctof(params[5]), amx_ctof(params[6]), amx_ctof(params[7])};
    double ra[3] = {atr(ang[0]), atr(ang[1]), atr(ang[2])};
    float dist = amx_ctof(params[8]);
    //just few simple formulas ^_^
    double up[3] = {sin(ra[1])*cos(ra[2]) + sin(ra[0])*sin(ra[2])*cos(ra[1]), sin(ra[2])*sin(ra[1]) - sin(ra[0])*cos(ra[1])*cos(ra[2]), -cos(ra[0])*cos(ra[1])};
    double right[3] = {-sin(ra[2])*cos(ra[0]), cos(ra[0])*cos(ra[2]), -sin(ra[0])};
    float ws, hs; cell oid; cell type = params[9];
    switch (type)
    {
        case  0: oid = 19464; ws = 5.875f; hs = 5.075f; break;
        case  2: oid = 2814; ws = 0.51f; hs = 0.51f; break;
        default: oid = 19372; ws = 3.18f; hs = 3.48f; break;
    }

    int blockx = (int)floor(float(picture.width()) / 15 + 0.999);
    int blocky = (int)floor(float(picture.height()) / 15 + 0.999);
   
    if(blockx*blocky > 1000)
    {
        logprintf("FAILED to create art: too large image");
        return 10;
    }

    unsigned int *temp_block = (unsigned int*)malloc(15*15*sizeof(unsigned int));
   
    a_vectors* vectores = new a_vectors();

    for (int i = 0; i < blockx; i++)
    {
        for(int j = 0; j < blocky; j++)
        {
            memset(temp_block, 0, sizeof(unsigned int)*15*15);
            CutBlock15(picture, temp_block, i, j);
            int index= i+j*blockx;
            float start[3] = {  (i - blockx/2.0)*ws*right[0] + (j - blocky/2.0)*(hs)*up[0] + pos[0],
                                (i - blockx/2.0)*ws*right[1] + (j - blocky/2.0)*(hs)*up[1] + pos[1],
                                (i - blockx/2.0)*ws*right[2] + (j - blocky/2.0)*(hs)*up[2] + pos[2]};

            int cur_w = CLIP(picture.width() - i*15,0,15);
            int cur_h = CLIP(picture.height() - j*15,0,15);
            char colors[4096] = {0};
            BuildString(colors, temp_block, cur_w, cur_h);
            cell cobid = 0;
            //let's create an object! [format: oid, sX, sY, sZ, aX, aY, aZ, dist]
            float add_rot = 0;
            if (oid == 2814)
            {
                add_rot = -94.65;
                cobid = g_Invoke->callNative(&PAWN::CreateObject, oid, start[0], start[1], start[2], ang[0], ang[1] + add_rot, 180 + ang[2], dist);

                vectores->arts_array.emplace(1, cobid);
                g_Invoke->callNative(&PAWN::SetObjectMaterialText, cobid, colors, 0, 140, "Webdings", 35, 0, 0, 0, 0);
                g_Invoke->callNative(&PAWN::SetObjectMaterial, cobid, 1, -1, "none", "none", 1);
            }
        }
    }
    free(temp_block);
    vectors.push_back(vectores);
    delete vectores;
    return vectors.size()-1;
}
Reply
#51

great job and +REP
Reply
#52

Until memory leak on client side is fixed, I recommend to not use this.
Reply
#53

Quote:
Originally Posted by TiW
Посмотреть сообщение
Do not want to open an image file on Linux (CentOS). I tried different ways ("/home/myprofile/img.png", "img.png", etc), all to no avail - FAILED to create art: can't load PNG picture
'myprofile' was just example, you should use your actual path

Quote:
Originally Posted by SDraw
Посмотреть сообщение
Until memory leak on client side is fixed, I recommend to not use this.
that thing happens while huge amount of text updates w/o recreating the object. I apply text only once, so it shouldn't leak
Reply
#54

Just a quick post to say, I look like hot shit in that picture in the first post of the thread.

Anyway, awesome work.
Reply
#55

Quote:
Originally Posted by DialUp
Посмотреть сообщение
'myprofile' was just example, you should use your actual path
I mean, I used my path..
Reply
#56

Quote:
Originally Posted by DialUp
Посмотреть сообщение
that thing happens while huge amount of text updates w/o recreating the object. I apply text only once, so it shouldn't leak
That's true when you use default object creation.
But if you use dynamic object creation this bug will make clients shit bricks :3
Reply
#57

Quote:
Originally Posted by DialUp
Посмотреть сообщение
Hello! Some time ago I made the tool for using pictures in your gamemodes. Now I present the plugin with that feature!

It wasn't easy to use the tool, but now is't VERY easy. Just use CreateArt / DestroyArt functions like CreateObject / DestroyObject ones:

I changed the pattern, now second parameter is the art type:
CreateArt(path_to_png_image, art_type, other_default_parameters...)

example:
Код:
#include <s-art>
.......
new art = CreateArt("D:\\my_image.png", 2, -704.1531, 1849.0200, 18,   45, 45, 45, 100); 
//picture should be in 24-bit PNG type
.......
DestroyArt(art);
also now it supports streamer plugin (use CreateDynamicArt).

I'm total noob in plugin writing, so you can modify, improve or do whatever you want with it.
SOURCE CODE
(include and DLL files are in /build/ folder)

demo:

yeah, that's what this thing was made for. To place the photo of Redirect_Left (owner and creator of sumo server) to the map.

currently plugin supports 4 size types:
type 2, size = X
type 3, size ~= 3*X
type 1, size ~= 6*X
type 0, size ~= 12*X

(it's not easy to find not-shadowed almost square single-textured objexts!!)
(if you do REALLY need another sizes, ask me, there're few less convenient objects unused)

size types:


The result isn't perfect, the objects I've used aren't square, so resize your original pictures to achieve better results.

It's still VERY recommended to use pictures with dimensions multiple of 15
is this only see you or all player in the server ?
Reply
#58

Heh, very originally and resourcefully
Fine fellow!
Reply
#59

Quote:
Originally Posted by SDraw
Посмотреть сообщение
That's true when you use default object creation.
But if you use dynamic object creation this bug will make clients shit bricks :3
oshi... ok

Quote:

is this only see you or all player in the server ?

all players
Reply
#60

DestroyArt does not work D:
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)