21

(2 відповідей, залишених у Інше)

дійшло

function SetScaleFactor(S, Suv)
{
    var magicConstant = 1000;
    var realS = S / Suv;
    this._fontScaleFactor = magicConstant / Math.sqrt(realS);
}

площа realS в нас ж відповідає квадратній текстурі, отже дорівнює x^2, тобто є показниковою функцію, і чим більший х будем брати, тим швидше буде рости її значення, тому для правильної пропорції беремо корінь
тепер все працює з ювелірною точністю)

22

(2 відповідей, залишених у Інше)

отак я досліджував підхід з такою функцією

function SetScaleFactor(S, Suv)
{
    var magicConstant = 1000;
    var realS = S / Suv; //знаходимо яку площу б покривала ця текстура, якби розгортка повністю заповнювала текстуру
    this._fontScaleFactor = magicConstant / realS;
}

так виглядають модель і текстура коли підібраний magicConstant = 12500, а S = 321, Suv = 0.509 і в результаті _fontScaleFactor = 19.79

Прихований текст

http://не-дійсний-домен/i9/6ff0685c46eb1979d5684df3b8f17c1e/1522747456/15516/1234465/tex1.jpghttp://не-дійсний-домен/a3/2018-04-03-09-24/i9-12215628/769x369-r/i.gif

тепер візьмемо модель вдвічі ширшу, де так само magicConstant = 12500, а S = 642, Suv = 0.258 і _fontScaleFactor = 5.01

Прихований текст

http://не-дійсний-домен/i9/61a77f2be6fd34624ea8172334de8762/1522748252/11040/1234465/tex2_800.jpghttp://не-дійсний-домен/a3/2018-04-03-09-37/i9-12215673/800x327-r/i.gif

тобто _fontScaleFactor вдвічі менший від того який мав би бути

але якщо ми візьмемо першу модель, та типу зробимо її квадратною (щоб висота дорівнювала ширині), де
magicConstant = 12500, а S = 623, Suv = 0.98 і _fontScaleFactor = 19.78

Прихований текст

http://не-дійсний-домен/i9/830470961a77291e4e172684dbe6b7dc/1522748593/16396/1234465/tex3.jpghttp://не-дійсний-домен/a3/2018-04-03-09-43/i9-12215693/759x439-r/i.gif

23

(2 відповідей, залишених у Інше)

Всім привіт
Намагаюся добитись ефекту, щоб написаний на текстурі 3д моделі текст завжди відповідав сталому фізичному розміру, незалежно від розміру моделі

Я генерую для моделі розгортку для тої її стіни на якій хочу писати

розгортка

Розгортка визначає як текстура лягає на модель. Тобто кожній тривимірній координаті ставить у відповідність двовимірну координату на текстурі. Ці координати прийнято називати uv, бо xyz вже зайняті визначаючи вершину у тривимірному просторі і також ці uv координати є нормалізованими, тобто набувають значень від 0 до 1, це зроблено для того щоб таку розгортку можна було легко застосувати до текстури любого розміру просто помноживши їх на її розмірність.

ліворуч - текстура та розгортка наній, праворуч - модель

http://i67.tinypic.com/13z5tm9.jpg

Після цього я аналізую всі трикутнички моделі попутно обчислюючи два значення
S - реальну площу cтіни(сторони) моделі для якої ми згенерували розгортку
Suv - типу площа розгортки на текстурі, тобто по суті получається коефіцієнт заповненості текстури 0 <= Suv <= 1

Я підозрюю що цих двох значень мало б бути достатньо, щоб знайти коефіцієнт який би правильно масштабував текст
Так виглядає моя остання спроба:

function SetScaleFactor(S, Suv)
{
    var magicConstant = 1000;
    var realS = S / Suv; //знаходимо яку площу б покривала ця текстура, якби розгортка повністю заповнювала текстуру
    this._fontScaleFactor = magicConstant / realS;
}

Але на чим більших моделях тестую(чим більша S), тим меншим получається розмір тексту за очікуваний

Які у вас ідеї як це можна поправити?
І якщо цікаві результати тестів чи ще якісь шмати коду теж кажіть, зараз і так не маю можливості їх прикріпити

то є норма

оті всякі маніпуляції типу 0/0, ∞-∞ і тд в контексті границь функції (а те про що йшлося вище якраз і є границями ф(+-1/х) при х->∞) дають невизначеність, і щоб її позбутись використовують правило Лопіталя

FakiNyan написав:

в мене тут думка з'явилась, а що, якщо ми не будемо перемножувати те, що виділене жовтим, а просто розкриємо дужки?

про яке перемноження ви говорите? зелене і синє рівняння якраз є наслідком розкриття дужок жовтого і зведення подібних доданків

висновок ваш виглядає правильниним

стосовно синього рівняння, продовжу з моменту коли ми розклали жовте на

зелене - синє

тепер додамо до нашого ріняння таку конструкцію яка ніяким чином його не змінить

зелене - синє + оранжеве - оранжеве

погрупуємо їх

(зелене + оранжеве) - (синє + оранжеве)

і тепер відповідно перша група перетворилась на червоне, а друга - на сіре
можете це перевірити вручну розкривши квадрат сірого рівняння

Betterthanyou написав:

Так в С++ використовується std::array, хіба ні ? Те що ви написали це С стиль.

C стиль, який успішно перекочував в С++
до речі ось і сам стандарт, де на 179 сторінці 8.3.4 йдеться про оголошення масивів

а std::array це бібліотечна обгортка над звичайними масивами

Betterthanyou написав:

Так я можу написати
https://msdn.microsoft.com/uk-ua/library/zb1574zs.aspx

Звичайно можете, тільки раз ви послуговуєтесь с++ ним бітсетом, то і не вмішуйте сюди сішний стандарт,
а с++11 стандарті масив ініціалізується constant-expression'ом


Yola написав:

Дійсно нема причин окрім бажання/небажання постачальників компліторів, щоб втілити масиви розмір яких визначається під час виконання. gcc дозволяє такі масиви. Але це інше ніж відмінні типи.

З масивами це всього лише скільки пам'яті виділити на стеку. І це можна визначати кожен раз при виклику функції в якій цей масив оголошено.

З типами інакше, щоб використовувати тип потрібно знати адреси всіх його функцій, і це треба знати під час компіляції. І взагалі, чи ця функція у типа є, бо bitset<5> і bitset<6> можуть мати різні набори членів.

Я розумію, я хотів донести інше, що як з шаблонами так і з масивами - їх тип\розмір повинен бути відомим на етапі компіляції, тому просту змінну туди і не засунути

Betterthanyou написав:

Можна вставити не константне значення у виклик функції з нетиповими параметрами шаблонів?
наприклад bitset

int b;
std::cin>>b;
std::bitset<b>(0b1100);

(Я вже пробував використовувати явні конвертації - не допомагають, помилка error: the value of ‘b’ is not usable in a constant expression)

По тій же причині, що ви не можете написати так:

int a;
cin >> a;
int arr[a];
Прихований текст

http://www.cplusplus.com/reference/bitset/bitset/
The size of a bitset is fixed at compile-time (determined by its template parameter).

ви викликаєте неконстантний гетер у константному методі

якщо ви початківець, то вам краще обарти рішення у якому все йде "з коробки", тоді ви зможете сконцентруватись на написанні коду, а не танцях з бубном довкола нього
тому як казали вище на перший час беріть microsoft visual studio
коли втомитесь від тормознутості студії переходьте на Qt Creator

33

(14 532 відповідей, залишених у Інше)

вона прийде коли ви будете завалені домашкою

34

(6 відповідей, залишених у C++)

спробуйте для початку просто вашим компілятором зібрати два варіанти, щоб визначити, чи проблема в тому, що чогось бракує вашій системі, чи cmake'у

виведіть ще sizeof(size_t), а то всяке буває

дивіться де вони посилаються на пункт 1.37

1) (a - b)^2 = a^2 + b^2 - 2*||a||*||b||*cos
2) (a - b)*(a - b) = a^2 - 2*a*b - b^2

(a - b)^2 = (a - b)*(a - b)   ==>>  1) і 2) еквівалентні

перпеписуємо праву частину 1) і 2) скоротивши (a^2 + b^2), які фігурують в  них обох

- 2*a*b = - 2*||a||*||b||*cos

а для чого вони це довели вам краще знати, ви підручник читаєте

37

(5 відповідей, залишених у C++)

Arete написав:

std::thread::hardware_concurrency() може повернути нуль, на який ви потім ділите.

Якщо я впевнений в тому що в мому компіляторі цей метод реалізований, то нормально буде на перший час обійтись таким рішенням?

int threadsCount = std::thread::hardware_concurrency() || 1;
koala написав:

По-третє, ви дивно обчислюєте кількість операцій на потік. Припустимо, є 4 ядра і 15 об'єктів. Тоді:
end = 14;//!
part = 14 / 4 = 3;//!!!
Потоки отримають:
i = 0 => 3 елементи
i = 1 => 3 елементи
i = 2 => 3 елементи
i = 3 => 5 елементів
Разом - 14 елементів. І сподіваюся, ваші потоки лізуть на дані іншого.

Я забув, що я не на форумі телепатів та не уточнив, що [start; end) формують напів-відкритий проміжок

for (i = start; i < end; i++){}

Тобто у випадку коли є 15 об'єктів - end=16

Але ваше зауваження наштовхнуло мене трохи  переобити алгоритм для більш збалансованого розподілу

float part =  (float)(end - start) / (float)threadsCount;
for (int i = 0; i < threadsCount; ++i)
{
    int startInd = part * i;
    int endInd = part * (i + 1);
    threads[i] = std::thread(threadFunc, startInd, endInd, std::ref(vertices));
}

i = 0 => 3
i = 1 => 4
i = 2 => 4
i = 3 => 4

koala написав:

Ну і по-четверте, не зовсім зрозуміло, нащо вам std::ref, тим більше, що threadFunc не reference_wrapper приймає.

у reference_wrapper реалізований оператор приведення до посилання operator T& ()
і використовувати його потрібно тому, що оскільки аргументи з якими створюється потік копіюються в новий стек, то передавши аргумент який має бути посиланням без std::ref в потоці ми отримаємо посилання на скопійований обк'єкт

Прихований текст

The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref).

38

(5 відповідей, залишених у C++)

Доброго вечора всім

Мав я значить один фор, який опрацьовував вектор vertices

Вирішив я його пришвидшити потоками: виніс тіло фору в функцію і передаю в неї межі які кожен конкретний потік має опрацювати
А по завершенню всі вони мають синхронізуватись, на тому ж місці де це зробив би і однопоточний фор

Гляньте чи не наткнусь я таким чином на якісь підводні камені, та і взагальному чи є якісь зауваження

void threadFunc(int startInd, int endInd, const std::vector<Vector3> & vertices);
int start = 0;
int end = vertices.size() - 1;
int threadsCount = std::thread::hardware_concurrency();
int part = (end - start) / threadsCount;

std::vector<std::thread> threads(threadsCount);
for (int i = 0; i < threadsCount; ++i)
{
    int startInd = part * i;
    int endInd = (i == threadsCount - 1) ? end : part * (i + 1);
    threads[i] = std::thread(threadFunc, startInd, std::ref(vertices));
}
for (int i = 0; i < threadsCount; ++i)
{
    threads[i].join();
}

По великому рахунку в кінцевому результаті різниці для користувача не буде, але насправді ж ви виконуєте лишнє копіювання об'єктів на які вказують вказівники data0 та data1.

В даному випадку це ускладнює тільки розуміння коду, але уявіть якби ці об'єкти були тяжкими, або їх було багато, тоді б це копіювання зайняло б чимало часу.

bool getData(int *data0, int *data1)
{
    int tmpdata0 = *data0;
    //*data0 - розіменовуєте вказівник, тобто ця операція поверне значення на яке він вказує
    // і воно скопіюється у змінну int tmpdata0

    readUInt(TSL2561_REG_DATA_0, &tmpdata0);
    //передаєте адресу копії у функцію readUInt, де вона присвоїться іншому вказівнику
    
   *data0 = tmpdata0;
   //повертаєтесь до початкового вказівника та замінюєте його попереднє значення
   //на значення цієї копії яка якось опрацювалась у функції readUInt

    return true;
}

Весь цей код скорочується до варіанту описаного у вашій першій функції: коли ви в readUInt передаєте безпосередньо вказівник, і тоді скопіюється лише вказівник, а не сам об'єкт.

bool getData(int *data0, int *data1)
{
    readUInt(TSL2561_REG_DATA_0, data0)
}

40

(4 відповідей, залишених у C++)

gets забрали в стандарті с11
використовуйте fgets натомість, або послуговуйтесь компілятором який підтримує старіші стандарти