Fix T43427: Particle system children sometimes not generated on reload
[blender.git] / source / blender / compositor / operations / COM_TextureOperation.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor: 
19  *              Jeroen Bakker 
20  *              Monique Dewanchand
21  */
22
23 #include "COM_TextureOperation.h"
24
25 #include "BLI_listbase.h"
26 #include "BKE_image.h"
27
28 TextureBaseOperation::TextureBaseOperation() : SingleThreadedOperation()
29 {
30         this->addInputSocket(COM_DT_VECTOR); //offset
31         this->addInputSocket(COM_DT_VECTOR); //size
32         this->m_texture = NULL;
33         this->m_inputSize = NULL;
34         this->m_inputOffset = NULL;
35         this->m_rd = NULL;
36         this->m_pool = NULL;
37         this->m_sceneColorManage = false;
38 }
39 TextureOperation::TextureOperation() : TextureBaseOperation()
40 {
41         this->addOutputSocket(COM_DT_COLOR);
42 }
43 TextureAlphaOperation::TextureAlphaOperation() : TextureBaseOperation()
44 {
45         this->addOutputSocket(COM_DT_VALUE);
46 }
47
48 void TextureBaseOperation::initExecution()
49 {
50         this->m_inputOffset = getInputSocketReader(0);
51         this->m_inputSize = getInputSocketReader(1);
52         this->m_pool = BKE_image_pool_new();
53         SingleThreadedOperation::initExecution();
54 }
55 void TextureBaseOperation::deinitExecution()
56 {
57         this->m_inputSize = NULL;
58         this->m_inputOffset = NULL;
59         BKE_image_pool_free(this->m_pool);
60         this->m_pool = NULL;
61         SingleThreadedOperation::deinitExecution();
62 }
63
64 void TextureBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
65 {
66         if (preferredResolution[0] == 0 || preferredResolution[1] == 0) {
67                 int width = this->m_rd->xsch * this->m_rd->size / 100;
68                 int height = this->m_rd->ysch * this->m_rd->size / 100;
69                 resolution[0] = width;
70                 resolution[1] = height;
71         }
72         else {
73                 resolution[0] = preferredResolution[0];
74                 resolution[1] = preferredResolution[1];
75         }
76 }
77
78 void TextureAlphaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
79 {
80         float color[4];
81         TextureBaseOperation::executePixelSampled(color, x, y, sampler);
82         output[0] = color[3];}
83
84 void TextureBaseOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
85 {
86         TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
87         float textureSize[4];
88         float textureOffset[4];
89         float vec[3];
90         int retval;
91         const float cx = this->getWidth() / 2;
92         const float cy = this->getHeight() / 2;
93         const float u = (x - cx) / this->getWidth() * 2;
94         const float v = (y - cy) / this->getHeight() * 2;
95
96         this->m_inputSize->readSampled(textureSize, x, y, sampler);
97         this->m_inputOffset->readSampled(textureOffset, x, y, sampler);
98
99         vec[0] = textureSize[0] * (u + textureOffset[0]);
100         vec[1] = textureSize[1] * (v + textureOffset[1]);
101         vec[2] = textureSize[2] * textureOffset[2];
102
103         retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres, m_pool, m_sceneColorManage, false);
104
105         if (texres.talpha)
106                 output[3] = texres.ta;
107         else
108                 output[3] = texres.tin;
109
110         if ((retval & TEX_RGB)) {
111                 output[0] = texres.tr;
112                 output[1] = texres.tg;
113                 output[2] = texres.tb;
114         }
115         else {
116                 output[0] = output[1] = output[2] = output[3];
117         }
118 }
119
120 MemoryBuffer *TextureBaseOperation::createMemoryBuffer(rcti *rect2)
121 {
122         int height = getHeight();
123         int width = getWidth();
124         DataType datatype = this->getOutputSocket()->getDataType();
125         int add = 4;
126         if (datatype == COM_DT_VALUE) {
127                 add = 1;
128         }
129
130         rcti rect;
131         rect.xmin = 0;
132         rect.ymin = 0;
133         rect.xmax = width;
134         rect.ymax = height;
135         MemoryBuffer *result = new MemoryBuffer(datatype, &rect);
136
137         float *data = result->getBuffer();
138
139         for (int y = 0; y < height; y++) {
140                 for (int x = 0; x < width; x++, data += add) {
141                         this->executePixelSampled(data, x, y, COM_PS_NEAREST);
142                 }
143         }
144
145         return result;
146 }