Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 12.02.2013, 13:59   #1
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию Свободная трансформация шрифтов

Откуда растут ноги
Пишу векторный-графический редактор (чёта типа AutoCAD). Ну как пишу... В основном пока в уме, конечно. Это конечно не AutoCAD, но некоторые его возможности должны быть реализованы. Вчастности изометрическое/перспективное отображение объектов. В том числе и текста, разумеется. Пошукал тему по трансформации шрифтов, ничего интересного кроме "любого угла наклона" не нашел, и то только для TrueType шрифтов.
Но кроме таких вкусностей, как вывода в изометрии, требуется еще и банальные на первый взгляд вещи, например получение ссылки на объект (вчастности на объект хранящий текст) по указаному пикселю на канве.
Подумал конечно о OpenGL и DirectX, но есть несколько НО. И моя некомпетенция в вопросах 3D далеко не первое НО, поверте. Вот примерный перечень ограничений:
- сложности соблюдения стандартов СПДС
- отсутствие некоторых специфических эффектов (а точнее сложность их реализации на OGL и DX)
- ограничения по кросплатформиности (пишу на Lazarus'е и всю геометрию реализую на уровне процессора)
- что делать с простыми 2D чертежами (на писать же для них отдельный движок, хотя как знать)
- отсутствие знаний соответствующих технологий (поверте, это был бы самый легкоустронимый недостаток)
Так что использование OpenGL и DirectX я исключил. Это можно оставить только для возможностей быстрого рендеринга.
Остается только один вариант - расчленить символы на примитивы и юзать линии, дуги и солиды. Уж их-то отобразить в изометрии труда не составит.

Вопрос
Как расчленить на примитивы или свободно трансформировать шрифт. Какие для этого есть инструменты и библиотеки.
Безымянный.jpg

Примечание
Замечания к разделу "Откуда растут ноги" тоже принимаются. Буду рад любым конструктивным замечаниям и предложениям.

Последний раз редактировалось Sibedir; 13.02.2013 в 06:54.
Sibedir вне форума Ответить с цитированием
Старый 13.02.2013, 19:33   #2
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

1. OpenGL вполне себе кроссплатформенный. Т.е. если требование кроссплатформенности исключает из рассмотрения DirectX, то с OpenGL ситуация другая.

2. TrueType, да и вообще все векторные шрифты вполне могут быть расчленены на примитивы. Что жек касается растровых шрифтов, то, во-первых, следует отдавать себе отчет, что их перспективное отображение неизбежно будет сопровождаться нежелательными артефактами (в силу самой природы растровых шрифтов). А в-вторых, для из отображения используется такая же методология, что и для отображения текстур, поэтому искать нужно именно по этому словосочетанию.
s-andriano вне форума Ответить с цитированием
Старый 14.02.2013, 07:06   #3
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию

Цитата:
Сообщение от s-andriano Посмотреть сообщение
1. OpenGL вполне себе кроссплатформенный. Т.е. если требование кроссплатформенности исключает из рассмотрения DirectX, то с OpenGL ситуация другая.
Да, кстати, к OpenGL это не относится. Спасибо, что поправили.
Но тем не менее, так OpenGL не умеет
1.JPG
Это изометрическое изображение некой детали с отрисовкой невидимых линий
Или такое
2.JPG
Это тоже самое, но для двух деталей и с указанием глубины прорисовки невидимых линий.
Утрированно, конечно, но нечто подобное частенько требуется на чертежах. Жутко напрягает, когда за отображение невидимых линий приходится самому заботиться.
----------------------------------------------------------------------------------------------------------------
Цитата:
Сообщение от s-andriano
2. TrueType, да и вообще все векторные шрифты вполне могут быть расчленены на примитивы.
s-andriano, я был бы чрезвычайно признателен, если бы хоть какую-то наводку дали, что искать, куда копать.
----------------------------------------------------------------------------------------------------------------
Цитата:
Сообщение от s-andriano
Что же касается растровых шрифтов, то, во-первых, следует отдавать себе отчет, что их перспективное отображение неизбежно будет сопровождаться нежелательными артефактами (в силу самой природы растровых шрифтов).
А что имеется ввиду? Крупные клеточки на переднем фоне или вы про что-то ещё?
----------------------------------------------------------------------------------------------------------------
Цитата:
Сообщение от s-andriano
А в-вторых, для их отображения используется такая же методология, что и для отображения текстур, поэтому искать нужно именно по этому словосочетанию.
Да, эт я уже понял. С ними по другому никак. Растр - он и в векторном чертеже растр.
1. Нарисовали его в квадратике
2. Исказили квадратик в соответствии с текущими параметрами просмотра (точки наблюдения. угла обзора, если это перспектива)
3. Отрисовали квадратик на холсте с использованием маски прозрачности
Каждую из этих задач в отдельности я уже решал. Не думаю, что возникнут проблемы с их реализацией в комплексе.
Но вот для векторных шрифтов (TTF, SHX) это не подходит. С SHX-шрифтами всё просто. Формат SHX довольно прост, я бы сказал примитивен. Но как же TTF расшрифтовать-то? Нашел вроде бы инфу по формату ( http://www.microsoft.com/typography/...sOverview.mspx ), но жутко не хочется писать модуль. Надеялся, что есть какие-то готовые подходящие решения.
Sibedir вне форума Ответить с цитированием
Старый 14.02.2013, 08:10   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

что именно огл не умеет? рисовать штриховкой? умеет.
а определять золны видимости вам все равн самим.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 14.02.2013, 12:31   #5
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
что именно огл не умеет? рисовать штриховкой? умеет.
а определять золны видимости вам все равн самим.
Согласен, можно поделить все грани на видимые и невидимые, отрисовывать только каркас (рёбра без граней), рёбра видимых граней рисовать сплошной, невидимых - прерывистой. Но проблема в том, что элементов на чертеже может быть over9000 и время затраченное на определение их взаимного положения уйдет уйма времени (причем уйма будет расти в геометрической прогрессии). А ведь ребро может быть и частично закрыто. Придётся ребро разбивать на участки (перекрыт/не перекрыт) и объединять смежные участки с одинаковым атрибутом перекрытости.
У меня же методика по дикому простая (я бы сказал тупая):
1. Выбираем грани повёрнутые нормалью к камере
2. Эти грани сортируются по удаленности от камеры
3. Рисуем от дальней к ближней (рёбра сплошные)
(эти три этапа OGL сделает в разы быстрее)
4. Рисуем весь каркас (только рёбра) прерывистой линией поверх уже нарисованного.
На Lazarus'е вот этот код
Код:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, Windows;

type

  { TForm1 }

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

type
  TFace3 = array [0..2] of TPoint;

var
  BM: Graphics.TBitmap;
  _V: Real = 0;
  _I: Integer = 0;
  FA: array of TFace3;
  FHigh, LHigh: Integer;

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  BM := Graphics.TBitmap.Create;
  BM.Width  := ClientWidth  - 20;
  BM.Height := ClientHeight - 20;

  FHigh := 9999;
  SetLength (FA, FHigh+1);
  Randomize;
  for i := 0 to FHigh do begin
    FA[i][0].X := Random(BM.Width); FA[i][0].Y := Random(BM.Height);
    FA[i][1].X := Random(BM.Width); FA[i][1].Y := Random(BM.Height);
    FA[i][2].X := Random(BM.Width); FA[i][2].Y := Random(BM.Height);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  BM.Free;
  BM := nil;
  SetLength (FA, 0);
end;

procedure TForm1.FormPaint(Sender: TObject);
var
  i: Integer;
  rd, rs: TRect;
  b, e: Cardinal;
begin
  b := GetTickCount;

  with rs do begin
    Top    := 0;
    Left   := 0;
    Right  := BM.Width;
    Bottom := BM.Height;
  end;

  with rd do begin
    Top    := 10;
    Left   := 10;
    Bottom := ClientHeight - 10;
    Right  := ClientWidth  - 10;
  end;

  with BM.Canvas do begin
    Brush.Style := bsSolid;
    Brush.Color := clWhite;
    FillRect (0, 0, BM.Width, BM.Height);

    Pen.Color := clBlack;
    Pen.Width := 2;
    for i := 0 to FHigh do begin
      Pen.Style := psClear;
      Polygon (FA[i]);
      Pen.Style := psSolid;
      MoveTo (FA[i][0]);
      LineTo (FA[i][1]);
      LineTo (FA[i][2]);
      LineTo (FA[i][0]);
    end;

    Pen.Width := 1;
    Pen.Style := psDash;
    for i := 0 to FHigh do begin
      MoveTo (FA[i][0]);
      LineTo (FA[i][1]);
      LineTo (FA[i][2]);
      LineTo (FA[i][0]);
    end;
  end;

  Canvas.CopyRect (rd, BM.Canvas, rs);

  e := GetTickCount;
  Inc (_I);
  _V := (_V*(_I-1) + e-b) / _I;
  Caption := 'V=' + IntToStr (Round (_V)) + '     I=' + IntToStr(_I);
end;

end.
Рисует 10000 граней ~ за 0,6 сек. Не самый лучший вариант. Крутить сложную модель будет довольно тяжко, т.к. к этому еще добавится перерасчет граней (геометрия, направление нормалей). Но когда схема уже разбита на примитивы и примитивы спроецированны на экран, и производится только зуммирование и сдвиг, цифра 0,6 вполне приемлема. Но всёравно, не фонтан.
Надо будет дома с Делфи сравнить. Я что-то подобное уже делал, работало гораздо шустрее.
...
М-м-мда, видимо придется всё-таки на OpenGL. Разобъём задачу на 2 части: 3D-моделирование и оформление чертежей. Тогда в 3D для моей задачи шрифты нафиг не нужны.

Последний раз редактировалось Sibedir; 14.02.2013 в 13:56.
Sibedir вне форума Ответить с цитированием
Старый 14.02.2013, 19:01   #6
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Цитата:
Сообщение от Sibedir Посмотреть сообщение
Но тем не менее, так OpenGL не умеет
...
Жутко напрягает, когда за отображение невидимых линий приходится самому заботиться.
Вы всерьез думаете, что без OpenGL Вам не придется об этом заботиться?

Могу посоветовать осуществлять вывод в два этапа
1. Сначала стилем предназначенным для невидимых линий рисуется объект без отсечения невидимых граней (либо с инверсией выбираемых граней).
2. А поверх - стилем, предназначенным для видимых линий - с отсечением.
Цитата:
s-andriano, я был бы чрезвычайно признателен, если бы хоть какую-то наводку дали, что искать, куда копать.
начните отсюда: http://ru.wikipedia.org/wiki/TrueType
Цитата:
А что имеется ввиду? Крупные клеточки на переднем фоне или вы про что-то ещё?
Можно назвать и так.
Цитата:
.
Но вот для векторных шрифтов (TTF, SHX) это не подходит. С SHX-шрифтами всё просто. Формат SHX довольно прост, я бы сказал примитивен. Но как же TTF расшрифтовать-то? Нашел вроде бы инфу по формату ( http://www.microsoft.com/typography/...sOverview.mspx ), но жутко не хочется писать модуль. Надеялся, что есть какие-то готовые подходящие решения.
Ну, это уж Вам решать, что именно делать и в каком объеме.
s-andriano вне форума Ответить с цитированием
Старый 14.02.2013, 19:24   #7
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Цитата:
Сообщение от Sibedir Посмотреть сообщение
У меня же методика по дикому простая (я бы сказал тупая):
1. Выбираем грани повёрнутые нормалью к камере
2. Эти грани сортируются по удаленности от камеры
3. Рисуем от дальней к ближней (рёбра сплошные)
(эти три этапа OGL сделает в разы быстрее)
Это называется алгоритмом художника, и он, увы, не обеспечивает правильной картинки.
Цитата:
Рисует 10000 граней ~ за 0,6 сек.
Издержки софтверного рендеринга.
s-andriano вне форума Ответить с цитированием
Старый 15.02.2013, 06:01   #8
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию

Цитата:
Сообщение от s-andriano
Вы всерьез думаете, что без OpenGL Вам не придется об этом заботиться?
Ну я как бы пытаюсь этого избежать, или по крайней мере минимизировать. При большом кол-ве элементов разделение линии на видимые и невидимые участки софтом займет большее (или не меньшее) время, чем отрисовка сплошных - закраска участков - отрисовка прерывистых (в основном это связано с накладными на выделение памяти под новые участки). А сил и времени на разработку займет много. Хотя, конечно, я могу и ошибаться.
Цитата:
Сообщение от s-andriano
Издержки софтверного рендеринга.
Всмысле, это очень долго, да?
Кстати дома на Делфи скорость в 3 раза выросла (комп немного мощьнее).
Короче я уже сказал, пока шрифты в баню, делим задачу на два направление (модель/чертеж), занимаемся OpenGL. Надо же было когда-то этим заняться.
Sibedir вне форума Ответить с цитированием
Старый 15.02.2013, 08:06   #9
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Цитата:
Сообщение от Sibedir Посмотреть сообщение
Ну я как бы пытаюсь этого избежать, или по крайней мере минимизировать.
И как эти попытки связаны с тем, кто будет генерить картинку - CPU или GPU?
Цитата:
При большом кол-ве элементов разделение линии на видимые и невидимые участки софтом займет большее (или не меньшее) время, чем отрисовка сплошных - закраска участков - отрисовка прерывистых (в основном это связано с накладными на выделение памяти под новые участки).
Вы, похоже, пропустили мимо ушей все мои замечания: и относительно того, что алгоритм художника не обеспечивает правильности картинки (нужно использовать z-буфер), и относительно отрисовки в два прохода: сначала все, а потом поверх только видимые.
Тут одна сортировка тысяч элементов по удаленности отнимает значительное время. А этого можно избежать.
s-andriano вне форума Ответить с цитированием
Старый 15.02.2013, 08:27   #10
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию

Нет, s-andriano, я не пропустил мимо ушей. Я вас прекрасно понял и про сортировку по Z и про алгоритм художника. Если нарисовать ВСЕ грани с положительной нормалью по алгоритму художника, а после нарисовать все рёбра пунктиром, то получится то, что мне нужно. Про это

тоже понял. Для моей задачи не критично.
Критичны 2 противопоставленных фактора:
- скорость работы алгоритма геометрии и механизмов вывода проекции на канву
- время затраченное на разработку
При этом еще требуется некая условность (схематичность) вывода.
Для разрешения дилеммы придется получить допсведения о механизмах реализации графики на огл и уточнить возможную сложность графических объектов (есть возможность разбить модель на подсхемы, а при выводе всей модели отображать некоторые детали схематично).
Это всё уже другая тема. Вопрос был в основном по шрифтам, но и за эти замечания спасибо всем. Бывает что сам уходишь в дебри и нужен просто оклик со стороны.

Последний раз редактировалось Sibedir; 15.02.2013 в 08:36.
Sibedir вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Свободная таблица Wind-up Bird Microsoft Office Access 5 03.05.2012 12:49
Свободная память fAttyboy Операционные системы общие вопросы 6 25.09.2011 21:17
Свободная память диска А vgikys1 Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 0 03.07.2010 22:14